fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER START
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The contents of this file are subject to the terms of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Common Development and Distribution License (the "License").
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You may not use this file except in compliance with the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * or http://www.opensolaris.org/os/licensing.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * See the License for the specific language governing permissions
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and limitations under the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If applicable, add the following below this CDDL HEADER, with the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER END
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Copyright 2000 by Cisco Systems, Inc. All rights reserved.
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
d72ea40e44b64f5cdf1bbf852c8887bbe45b3dbeDan McDonald * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iSCSI Pseudo HBA Driver
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/socket.h> /* networking stuff */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/t_kuser.h> /* networking stuff */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/tihdr.h> /* networking stuff */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/strsubr.h> /* networking stuff */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <netinet/tcp.h> /* TCP_NODELAY */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/socketvar.h> /* _ALLOC_SLEEP */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/strsun.h> /* DB_TYPE() */
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China#include <sys/scsi/generic/sense.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include "iscsi.h" /* iscsi driver */
1a1a84a324206b6b1f5f704ab166c4ebf78aed76Peter Dunlap#include <sys/iscsi_protocol.h> /* iscsi protocol */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#define ISCSI_INI_TASK_TTT 0xffffffff
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China#define ISCSI_CONN_TIEMOUT_DETECT 20
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapboolean_t iscsi_io_logging = B_FALSE;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#define ISCSI_CHECK_SCSI_READ(ICHK_CMD, ICHK_HDR, ICHK_LEN, ICHK_TYPE) \
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (idm_pattern_checking) { \
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap struct scsi_pkt *pkt = (ICHK_CMD)->cmd_un.scsi.pkt; \
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (((ICHK_HDR)->response == 0) && \
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ((ICHK_HDR)->cmd_status == 0) && \
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ((pkt->pkt_cdbp[0] == SCMD_READ_G1) || \
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (pkt->pkt_cdbp[0] == SCMD_READ_G4) || \
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (pkt->pkt_cdbp[0] == SCMD_READ) || \
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (pkt->pkt_cdbp[0] == SCMD_READ_G5))) { \
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_buf_t *idb = (ICHK_CMD)->cmd_un.scsi.ibp_ibuf; \
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap IDM_BUFPAT_CHECK(idb, ICHK_LEN, ICHK_TYPE); \
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } \
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik/* Size of structure scsi_arq_status without sense data. */
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik#define ISCSI_ARQ_STATUS_NOSENSE_LEN (sizeof (struct scsi_arq_status) - \
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik sizeof (struct scsi_extended_sense))
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* generic io helpers */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic uint32_t n2h24(uchar_t *ptr);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int iscsi_sna_lt(uint32_t n1, uint32_t n2);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapvoid iscsi_update_flow_control(iscsi_sess_t *isp,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t max, uint32_t exp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic iscsi_status_t iscsi_rx_process_scsi_itt_to_icmdp(iscsi_sess_t *isp,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_conn_t *ic, iscsi_scsi_rsp_hdr_t *ihp, iscsi_cmd_t **icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic iscsi_status_t iscsi_rx_process_itt_to_icmdp(iscsi_sess_t *isp,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_hdr_t *ihp, iscsi_cmd_t **icmdp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void iscsi_process_rsp_status(iscsi_sess_t *isp, iscsi_conn_t *icp,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_status_t status);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void iscsi_drop_conn_cleanup(iscsi_conn_t *icp);
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing Chinastatic boolean_t iscsi_nop_timeout_checks(iscsi_cmd_t *icmdp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/* callbacks from idm */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic idm_pdu_cb_t iscsi_tx_done;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/* receivers */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic idm_status_t iscsi_rx_process_nop(idm_conn_t *ic, idm_pdu_t *pdu);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic idm_status_t iscsi_rx_process_data_rsp(idm_conn_t *ic,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_t *pdu);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic idm_status_t iscsi_rx_process_cmd_rsp(idm_conn_t *ic, idm_pdu_t *pdu);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic idm_status_t iscsi_rx_process_reject_rsp(idm_conn_t *ic,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_t *pdu);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic idm_status_t iscsi_rx_process_rejected_tsk_mgt(idm_conn_t *ic,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_hdr_t *old_ihp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic idm_status_t iscsi_rx_process_task_mgt_rsp(idm_conn_t *ic,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_t *pdu);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic idm_status_t iscsi_rx_process_logout_rsp(idm_conn_t *ic,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_t *pdu);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic idm_status_t iscsi_rx_process_async_rsp(idm_conn_t *ic,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_t *pdu);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic idm_status_t iscsi_rx_process_text_rsp(idm_conn_t *ic,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_t *pdu);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* senders */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic iscsi_status_t iscsi_tx_scsi(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic iscsi_status_t iscsi_tx_nop(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic iscsi_status_t iscsi_tx_abort(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic iscsi_status_t iscsi_tx_reset(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic iscsi_status_t iscsi_tx_logout(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic iscsi_status_t iscsi_tx_text(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* helpers */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void iscsi_logout_start(void *arg);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void iscsi_handle_passthru_callback(struct scsi_pkt *pkt);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void iscsi_handle_nop(iscsi_conn_t *icp, uint32_t itt, uint32_t ttt);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void iscsi_timeout_checks(iscsi_sess_t *isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void iscsi_nop_checks(iscsi_sess_t *isp);
904e51f67bfac9f3ec88d9254757474c448808ebJack Mengstatic boolean_t iscsi_decode_sense(uint8_t *sense_data, iscsi_cmd_t *icmdp);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing Chinastatic void iscsi_flush_cmd_after_reset(uint32_t cmd_sn, uint16_t lun_num,
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China iscsi_conn_t *icp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This file contains the main guts of the iSCSI protocol layer.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * It's broken into 5 sections; Basic helper functions, RX IO path,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * TX IO path, Completion (IC) IO path, and watchdog (WD) routines.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The IO flow model is similiar to the below diagram. The
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi session, connection and command state machines are used
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to drive IO through this flow diagram. Reference those files
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to get a detailed description of their respective state models
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * prior to their xxx_state_machine_function().
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * tran_start() -> CMD_E1 TX_THREAD RX_THREAD
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * | T T
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * V T T
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * PENDING_Q --CMD_E2--> ACTIVE_Q - --CMD_E3--+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * T \ C T |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * T \M T |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * D T |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * WD_THREAD TT|TT T |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * /E T |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * / 6 T |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ABORTING_Q<- --CMD_E3--+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * T |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * T T |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * T |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * callback() <--CMD_E#-- COMPLETION_Q <------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * T
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * T
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * IC_THREAD
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * External and internal command are ran thru this same state
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * machine. All commands enter the state machine by receiving an
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ISCSI_CMD_EVENT_E1. This event places the command into the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * PENDING_Q. Next when resources are available the TX_THREAD
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * issues a E2 event on the command. This sends the command
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to the TCP stack and places the command on the ACTIVE_Q. While
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * on the PENDIING_Q and ACTIVE_Q, the command is monitored via the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * WD_THREAD to ensure the pkt_time has not elapsed. If elapsed the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * command is issued an E6(timeout) event which moves either (if pending)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * completed the command or (if active) moves the command to the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * aborting queue and issues a SCSI TASK MANAGEMENT ABORT command
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to cancel the IO request. If the original command is completed
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * or the TASK MANAGEMENT command completes the command is moved
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to the COMPLETION_Q via a E3 event. The IC_THREAD then processes
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the COMPLETION_Q and issues the scsi_pkt callback. This
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * callback can not be processed directly from the RX_THREAD
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * because the callback might call back into the iscsi driver
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * causing a deadlock condition.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * For more details on the complete CMD state machine reference
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the state machine diagram in iscsi_cmd.c. The connection state
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * machine is driven via IO events in this file. Then session
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * events are driven by the connection events. For complete
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * details on these state machines reference iscsi_sess.c and
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_conn.c
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * | io helper routines |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * n2h24 - native to host 24 bit integer translation.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic uint32_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forten2h24(uchar_t *ptr)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t idx;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(ptr, &idx, 3);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ntohl(idx) >> 8);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_sna_lt - Serial Number Arithmetic, 32 bits, less than, RFC1982
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_sna_lt(uint32_t n1, uint32_t n2)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return ((n1 != n2) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (((n1 < n2) && ((n2 - n1) < ISCSI_SNA32_CHECK)) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ((n1 > n2) && ((n1 - n2) > ISCSI_SNA32_CHECK))));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_sna_lte - Serial Number Arithmetic, 32 bits, less than or equal,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * RFC1982
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteint
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_sna_lte(uint32_t n1, uint32_t n2)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return ((n1 == n2) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (((n1 < n2) && ((n2 - n1) < ISCSI_SNA32_CHECK)) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ((n1 > n2) && ((n1 - n2) > ISCSI_SNA32_CHECK))));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_update_flow_control - Update expcmdsn and maxcmdsn iSCSI
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * flow control information for a session
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapvoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_update_flow_control(iscsi_sess_t *isp, uint32_t max, uint32_t exp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(mutex_owned(&isp->sess_cmdsn_mutex));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!iscsi_sna_lt(max, (exp - 1))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!iscsi_sna_lte(exp, isp->sess_expcmdsn)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte isp->sess_expcmdsn = exp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!iscsi_sna_lte(max, isp->sess_maxcmdsn)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte isp->sess_maxcmdsn = max;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (iscsi_sna_lte(isp->sess_cmdsn,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte isp->sess_maxcmdsn)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the window is open again - schedule
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to send any held tasks soon
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_sess_redrive_io(isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * | io receive and processing routines |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * iscsi_rx_scsi_rsp - called from idm
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * For each opcode type fan out the processing.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_rx_scsi_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_conn_t *icp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_sess_t *isp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_hdr_t *ihp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_status_t status;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(ic != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(pdu != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icp = ic->ic_handle;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icp != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ihp = (iscsi_hdr_t *)pdu->isp_hdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(ihp != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap isp = icp->conn_sess;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* reset the session timer when we receive the response */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap isp->sess_rx_lbolt = icp->conn_rx_lbolt = ddi_get_lbolt();
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* fan out the hdr processing */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (ihp->opcode & ISCSI_OPCODE_MASK) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_OP_SCSI_DATA_RSP:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = iscsi_rx_process_data_rsp(ic, pdu);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_OP_SCSI_RSP:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = iscsi_rx_process_cmd_rsp(ic, pdu);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_complete(pdu, status);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte default:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "received pdu with unsupported opcode 0x%02x",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icp->conn_oid, ihp->opcode);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = IDM_STATUS_PROTOCOL_ERROR;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_process_rsp_status(isp, icp, status);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapvoid
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_task_cleanup(int opcode, iscsi_cmd_t *icmdp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap struct buf *bp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_buf_t *ibp, *obp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_task_t *itp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap itp = icmdp->cmd_itp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(itp != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT((opcode == ISCSI_OP_SCSI_DATA_RSP) ||
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (opcode == ISCSI_OP_SCSI_RSP));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bp = icmdp->cmd_un.scsi.bp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ibp = icmdp->cmd_un.scsi.ibp_ibuf;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap obp = icmdp->cmd_un.scsi.ibp_obuf;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISCSI_IO_LOG(CE_NOTE, "DEBUG: task_cleanup: itp: %p opcode: %d "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "icmdp: %p bp: %p ibp: %p", (void *)itp, opcode,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (void *)icmdp, (void *)bp, (void *)ibp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (bp && bp->b_bcount) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (ibp != NULL && bp->b_flags & B_READ) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_buf_unbind_in(itp, ibp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_buf_free(ibp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.ibp_ibuf = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else if (obp != NULL && !(bp->b_flags & B_READ)) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_buf_unbind_out(itp, obp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_buf_free(obp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.ibp_obuf = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_task_done(itp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapidm_status_t
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_rx_chk(iscsi_conn_t *icp, iscsi_sess_t *isp,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_scsi_rsp_hdr_t *irhp, iscsi_cmd_t **icmdp)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_status_t rval;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&isp->sess_cmdsn_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (icp->conn_expstatsn == ntohl(irhp->statsn)) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icp->conn_expstatsn++;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap cmn_err(CE_WARN, "iscsi connection(%u/%x) protocol error - "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "received status out of order itt:0x%x statsn:0x%x "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "expstatsn:0x%x", icp->conn_oid, irhp->opcode,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap irhp->itt, ntohl(irhp->statsn), icp->conn_expstatsn);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_cmdsn_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_PROTOCOL_ERROR);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* get icmdp so we can cleanup on error */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if ((irhp->opcode == ISCSI_OP_SCSI_DATA_RSP) ||
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (irhp->opcode == ISCSI_OP_SCSI_RSP)) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap rval = iscsi_rx_process_scsi_itt_to_icmdp(isp, icp->conn_ic,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap irhp, icmdp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap rval = iscsi_rx_process_itt_to_icmdp(isp,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (iscsi_hdr_t *)irhp, icmdp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (!ISCSI_SUCCESS(rval)) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&isp->sess_cmdsn_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_PROTOCOL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* update expcmdsn and maxcmdsn */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_update_flow_control(isp, ntohl(irhp->maxcmdsn),
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ntohl(irhp->expcmdsn));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_cmdsn_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_SUCCESS);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_cmd_rsp_chk(iscsi_cmd_t *icmdp, iscsi_scsi_rsp_hdr_t *issrhp)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap struct scsi_pkt *pkt;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap size_t data_transferred;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt = icmdp->cmd_un.scsi.pkt;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_resid = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap data_transferred = icmdp->cmd_un.scsi.data_transferred;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Check the residual count */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if ((icmdp->cmd_un.scsi.bp) &&
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (data_transferred != icmdp->cmd_un.scsi.bp->b_bcount)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * We didn't xfer the expected amount of data -
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * the residual_count in the header is only
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * valid if the underflow flag is set.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (issrhp->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_resid = ntohl(issrhp->residual_count);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (icmdp->cmd_un.scsi.bp->b_bcount >
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap data_transferred) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Some data fell on the floor
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * somehow - probably a CRC error
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_resid =
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.bp->b_bcount -
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap data_transferred;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISCSI_IO_LOG(CE_NOTE,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "DEBUG: iscsi_rx_cmd_rsp_chk: itt: %u"
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "data_trans != b_count data_transferred: %lu "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "b_count: %lu cmd_status: %d flags: %d resid: %lu",
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap issrhp->itt, data_transferred,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.bp->b_bcount,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap issrhp->cmd_status & STATUS_MASK,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap issrhp->flags, pkt->pkt_resid);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* set flags that tell SCSA that the command is complete */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (icmdp->cmd_crc_error_seen == B_FALSE) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Set successful completion */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_reason = CMD_CMPLT;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (icmdp->cmd_un.scsi.bp) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_state |= (STATE_XFERRED_DATA |
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap STATE_GOT_STATUS);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_state |= STATE_GOT_STATUS;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Some of the data was found to have an incorrect
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * error at the protocol error.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_reason = CMD_PER_FAIL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_statistics |= STAT_PERR;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (icmdp->cmd_un.scsi.bp) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_resid =
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.bp->b_bcount;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_resid = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing Chinastatic boolean_t
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_cmd_rsp_cmd_status(iscsi_cmd_t *icmdp, iscsi_scsi_rsp_hdr_t *issrhp,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap uint8_t *data)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik int32_t dlength;
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik struct scsi_arq_status *arqstat;
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik size_t senselen;
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik int32_t statuslen;
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik int32_t sensebuf_len;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap struct scsi_pkt *pkt;
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik boolean_t affect = B_FALSE;
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik int32_t senselen_to_copy;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt = icmdp->cmd_un.scsi.pkt;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap dlength = n2h24(issrhp->dlength);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Process iSCSI Cmd Response Status
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * RFC 3720 Sectionn 10.4.2.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap switch (issrhp->cmd_status & STATUS_MASK) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap case STATUS_GOOD:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* pass SCSI status up stack */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (pkt->pkt_scbp) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_scbp[0] = issrhp->cmd_status;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap break;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap case STATUS_CHECK:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Verify we received a sense buffer and
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * that there is the correct amount of
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * request sense space to copy it to.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if ((dlength > 1) &&
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (pkt->pkt_scbp != NULL) &&
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (icmdp->cmd_un.scsi.statuslen >=
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap sizeof (struct scsi_arq_status))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * If a bad command status is received we
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * need to reset the pkt_resid to zero.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * The target driver compares its value
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * before checking other error flags.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * (ex. check conditions)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_resid = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* get sense length from first 2 bytes */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap senselen = ((data[0] << 8) | data[1]) &
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (size_t)0xFFFF;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISCSI_IO_LOG(CE_NOTE,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "DEBUG: iscsi_rx_cmd_rsp_cmd_status status_check: "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "dlen: %d scbp: %p statuslen: %d arq: %d senselen:"
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap " %lu", dlength, (void *)pkt->pkt_scbp,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.statuslen,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (int)sizeof (struct scsi_arq_status),
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap senselen);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Sanity-check on the sense length */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if ((senselen + 2) > dlength) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap senselen = dlength - 2;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * If there was a Data Digest error then
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * the sense data cannot be trusted.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (icmdp->cmd_crc_error_seen) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap senselen = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* automatic request sense */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap arqstat =
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (struct scsi_arq_status *)pkt->pkt_scbp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* pass SCSI status up stack */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap *((uchar_t *)&arqstat->sts_status) =
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap issrhp->cmd_status;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Set the status for the automatic
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * request sense command
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap arqstat->sts_rqpkt_state = (STATE_GOT_BUS |
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap STATE_GOT_TARGET | STATE_SENT_CMD |
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap STATE_XFERRED_DATA | STATE_GOT_STATUS |
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap STATE_ARQ_DONE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap *((uchar_t *)&arqstat->sts_rqpkt_status) =
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap STATUS_GOOD;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap arqstat->sts_rqpkt_reason = CMD_CMPLT;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap statuslen = icmdp->cmd_un.scsi.statuslen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (senselen == 0) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* auto request sense failed */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap arqstat->sts_rqpkt_status.sts_chk = 1;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap arqstat->sts_rqpkt_resid = statuslen;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else if (senselen < statuslen) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* auto request sense short */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap arqstat->sts_rqpkt_resid = statuslen - senselen;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* auto request sense complete */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap arqstat->sts_rqpkt_resid = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap arqstat->sts_rqpkt_statistics = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_state |= STATE_ARQ_DONE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_XARQ) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_state |= STATE_XARQ_DONE;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik /*
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik * Calculate size of space reserved for sense data in
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik * pkt->pkt_scbp.
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik */
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik sensebuf_len = statuslen - ISCSI_ARQ_STATUS_NOSENSE_LEN;
5279807d7e1818eac6f90ac640b7a89cdb37522dJack Meng
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* copy auto request sense */
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik senselen_to_copy = min(senselen, sensebuf_len);
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik if (senselen_to_copy > 0) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bcopy(&data[2], (uchar_t *)&arqstat->
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik sts_sensedata, senselen_to_copy);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China affect = iscsi_decode_sense(
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng (uint8_t *)&arqstat->sts_sensedata, icmdp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik arqstat->sts_rqpkt_resid = sensebuf_len -
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik senselen_to_copy;
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik ISCSI_IO_LOG(CE_NOTE, "DEBUG: iscsi_cmd_rsp_cmd_status:"
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik " sts_rqpkt_resid: %d pkt_scblen: %d senselen: %lu"
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik " sensebuf_len: %d senselen_to_copy: %d affect: %d",
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik arqstat->sts_rqpkt_resid, pkt->pkt_scblen, senselen,
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik sensebuf_len, senselen_to_copy, affect);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* FALLTHRU */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap case STATUS_BUSY:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap case STATUS_RESERVATION_CONFLICT:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap case STATUS_QFULL:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap case STATUS_ACA_ACTIVE:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap default:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * If a bad command status is received we need to
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * reset the pkt_resid to zero. The target driver
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * compares its value before checking other error
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * flags. (ex. check conditions)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISCSI_IO_LOG(CE_NOTE,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "DEBUG: iscsi_rx_cmd_rsp_cmd_status: status: "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "%d cmd_status: %d dlen: %u scbp: %p statuslen: %d "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "arg_len: %d", issrhp->cmd_status & STATUS_MASK,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap issrhp->cmd_status, dlength, (void *)pkt->pkt_scbp,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.statuslen,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (int)sizeof (struct scsi_arq_status));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_resid = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* pass SCSI status up stack */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (pkt->pkt_scbp) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_scbp[0] = issrhp->cmd_status;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China return (affect);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * iscsi_rx_process_login_pdup - Process login response PDU. This function
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * copies the data into the connection context so that the login code can
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * interpret it.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapidm_status_t
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_rx_process_login_pdu(idm_conn_t *ic, idm_pdu_t *pdu)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_conn_t *icp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icp = ic->ic_handle;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Copy header and data into connection structure so iscsi_login()
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * can process it.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_enter(&icp->conn_login_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * If conn_login_state != LOGIN_TX then we are not ready to handle
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * this login response and we should just drop it.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (icp->conn_login_state == LOGIN_TX) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icp->conn_login_datalen = pdu->isp_datalen;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bcopy(pdu->isp_hdr, &icp->conn_login_resp_hdr,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap sizeof (iscsi_hdr_t));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Login code is sloppy with it's NULL handling so make sure
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * we don't leave any stale data in there.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bzero(icp->conn_login_data, icp->conn_login_max_data_length);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bcopy(pdu->isp_data, icp->conn_login_data,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap MIN(pdu->isp_datalen, icp->conn_login_max_data_length));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_login_update_state_locked(icp, LOGIN_RX);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&icp->conn_login_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_SUCCESS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_rx_process_cmd_rsp - Process received scsi command response. This
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * will contain sense data if the command was not successful. This data needs
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to be copied into the scsi_pkt. Otherwise we just complete the IO.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic idm_status_t
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_rx_process_cmd_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_conn_t *icp = ic->ic_handle;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_sess_t *isp = icp->conn_sess;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_scsi_rsp_hdr_t *issrhp = (iscsi_scsi_rsp_hdr_t *)pdu->isp_hdr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap uint8_t *data = pdu->isp_data;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_cmd_t *icmdp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap struct scsi_pkt *pkt = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_status_t rval;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap struct buf *bp;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China boolean_t flush = B_FALSE;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China uint32_t cmd_sn = 0;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China uint16_t lun_num = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* make sure we get status in order */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_enter(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if ((rval = iscsi_rx_chk(icp, isp, issrhp,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap &icmdp)) != IDM_STATUS_SUCCESS) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (icmdp != NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_task_cleanup(issrhp->opcode, icmdp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (rval);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * If we are in "idm aborting" state then we shouldn't continue
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * to process this command. By definition this command is no longer
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * on the active queue so we shouldn't try to remove it either.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_enter(&icmdp->cmd_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (icmdp->cmd_state == ISCSI_CMD_STATE_IDM_ABORTING) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&icmdp->cmd_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_SUCCESS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&icmdp->cmd_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Get the IDM buffer and bytes transferred */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bp = icmdp->cmd_un.scsi.bp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (ic->ic_conn_flags & IDM_CONN_USE_SCOREBOARD) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Transport tracks bytes transferred so use those counts */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (bp && (bp->b_flags & B_READ)) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.data_transferred +=
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_itp->idt_rx_bytes;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.data_transferred +=
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_itp->idt_tx_bytes;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Some transports cannot track the bytes transferred on
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * the initiator side (like iSER) so we have to use the
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * status info. If the response field indicates that
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * the command actually completed then we will assume
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * the data_transferred value represents the entire buffer
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * unless the resid field says otherwise. This is a bit
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * unintuitive but it's really impossible to know what
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * has been transferred without detailed consideration
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * of the SCSI status and sense key and that is outside
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * the scope of the transport. Instead the target/class driver
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * can consider these values along with the resid and figure
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * it out. The data_transferred concept is just belt and
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * suspenders anyway -- RFC 3720 actually explicitly rejects
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * scoreboarding ("Initiators SHOULD NOT keep track of the
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * data transferred to or from the target (scoreboarding)")
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * perhaps for this very reason.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (issrhp->response != 0) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.data_transferred = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.data_transferred =
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (bp == NULL) ? 0 : bp->b_bcount;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (issrhp->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.data_transferred -=
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ntohl(issrhp->residual_count);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISCSI_CHECK_SCSI_READ(icmdp, issrhp,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.data_transferred,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap BP_CHECK_THOROUGH);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISCSI_IO_LOG(CE_NOTE, "DEBUG: rx_process_cmd_rsp: ic: %p pdu: %p itt:"
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap " %x expcmdsn: %x sess_cmd: %x sess_expcmdsn: %x data_transfered:"
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap " %lu ibp: %p obp: %p", (void *)ic, (void *)pdu, issrhp->itt,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap issrhp->expcmdsn, isp->sess_cmdsn, isp->sess_expcmdsn,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.data_transferred,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (void *)icmdp->cmd_un.scsi.ibp_ibuf,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (void *)icmdp->cmd_un.scsi.ibp_obuf);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_task_cleanup(issrhp->opcode, icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (issrhp->response) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* The target failed the command. */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISCSI_IO_LOG(CE_NOTE, "DEBUG: rx_process_cmd_rsp: ic: %p pdu:"
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap " %p response: %d bcount: %lu", (void *)ic, (void *)pdu,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap issrhp->response, icmdp->cmd_un.scsi.bp->b_bcount);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt = icmdp->cmd_un.scsi.pkt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pkt->pkt_reason = CMD_TRAN_ERR;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icmdp->cmd_un.scsi.bp) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pkt->pkt_resid = icmdp->cmd_un.scsi.bp->b_bcount;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pkt->pkt_resid = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* success */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_cmd_rsp_chk(icmdp, issrhp);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China flush = iscsi_cmd_rsp_cmd_status(icmdp, issrhp, data);
b97c1f925a1d211d325cdc3a2e4b3b779082510bMilos Muzik
b97c1f925a1d211d325cdc3a2e4b3b779082510bMilos Muzik ASSERT(icmdp->cmd_lun == NULL || icmdp->cmd_lun->lun_num ==
b97c1f925a1d211d325cdc3a2e4b3b779082510bMilos Muzik (icmdp->cmd_un.scsi.lun & ISCSI_LUN_MASK));
b97c1f925a1d211d325cdc3a2e4b3b779082510bMilos Muzik
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China if (flush == B_TRUE) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China cmd_sn = icmdp->cmd_sn;
b97c1f925a1d211d325cdc3a2e4b3b779082510bMilos Muzik lun_num = icmdp->cmd_un.scsi.lun & ISCSI_LUN_MASK;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China if (flush == B_TRUE) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China iscsi_flush_cmd_after_reset(cmd_sn, lun_num, icp);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_SUCCESS);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_data_rsp_pkt(iscsi_cmd_t *icmdp, iscsi_data_rsp_hdr_t *idrhp)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap struct buf *bp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap size_t data_transferred;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap struct scsi_pkt *pkt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bp = icmdp->cmd_un.scsi.bp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt = icmdp->cmd_un.scsi.pkt;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap data_transferred = icmdp->cmd_un.scsi.data_transferred;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * The command* must be completed now, since we won't get a command
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * response PDU. The cmd_status and residual_count are
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * not meaningful unless status_present is set.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_resid = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Check the residual count */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (bp && (data_transferred != bp->b_bcount)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * We didn't xfer the expected amount of data -
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * the residual_count in the header is only valid
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * if the underflow flag is set.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (idrhp->flags & ISCSI_FLAG_DATA_UNDERFLOW) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_resid = ntohl(idrhp->residual_count);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISCSI_IO_LOG(CE_NOTE, "DEBUG: iscsi_data_rsp_pkt: "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "underflow: itt: %d "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "transferred: %lu count: %lu", idrhp->itt,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap data_transferred, bp->b_bcount);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (bp->b_bcount > data_transferred) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Some data fell on the floor somehw */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISCSI_IO_LOG(CE_NOTE, "DEBUG: "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "iscsi_data_rsp_pkt: data fell: itt: %d "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "transferred: %lu count: %lu", idrhp->itt,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap data_transferred, bp->b_bcount);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_resid =
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bp->b_bcount - data_transferred;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_reason = CMD_CMPLT;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_state |= (STATE_XFERRED_DATA | STATE_GOT_STATUS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (((idrhp->cmd_status & STATUS_MASK) != STATUS_GOOD) &&
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (icmdp->cmd_un.scsi.statuslen >=
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap sizeof (struct scsi_arq_status)) && pkt->pkt_scbp) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Not supposed to get exception status here!
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * We have no request sense data so just do the
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * best we can
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap struct scsi_arq_status *arqstat =
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (struct scsi_arq_status *)pkt->pkt_scbp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bzero(arqstat, sizeof (struct scsi_arq_status));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap *((uchar_t *)&arqstat->sts_status) =
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idrhp->cmd_status;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik /* sense residual is set to whole size of sense buffer */
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik arqstat->sts_rqpkt_resid = icmdp->cmd_un.scsi.statuslen -
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik ISCSI_ARQ_STATUS_NOSENSE_LEN;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISCSI_IO_LOG(CE_NOTE, "DEBUG: iscsi_data_rsp_pkt: "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "exception status: itt: %d resid: %d",
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idrhp->itt, arqstat->sts_rqpkt_resid);
b424305435881ac456a9343be2898f1f86440f31Sheng-Liang Eric Zhang
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else if (pkt->pkt_scbp) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* just pass along the status we got */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_scbp[0] = idrhp->cmd_status;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * iscsi_rx_process_data_rsp -
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * This currently processes the final data sequence denoted by the data response
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * PDU Status bit being set. We will not receive the SCSI response.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * This bit denotes that the PDU is the successful completion of the
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * command.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic idm_status_t
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_rx_process_data_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_sess_t *isp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_data_rsp_hdr_t *idrhp = (iscsi_data_rsp_hdr_t *)pdu->isp_hdr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_cmd_t *icmdp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap struct buf *bp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_conn_t *icp = ic->ic_handle;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_buf_t *ibp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_status_t rval;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* should only call this when the data rsp contains final rsp */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(idrhp->flags & ISCSI_FLAG_DATA_STATUS);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap isp = icp->conn_sess;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if ((rval = iscsi_rx_chk(icp, isp, (iscsi_scsi_rsp_hdr_t *)idrhp,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap &icmdp)) != IDM_STATUS_SUCCESS) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (icmdp != NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_task_cleanup(idrhp->opcode, icmdp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (rval);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * If we are in "idm aborting" state then we shouldn't continue
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * to process this command. By definition this command is no longer
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * on the active queue so we shouldn't try to remove it either.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&icmdp->cmd_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (icmdp->cmd_state == ISCSI_CMD_STATE_IDM_ABORTING) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&icmdp->cmd_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_SUCCESS);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&icmdp->cmd_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Holding the pending/active queue locks across the
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * iscsi_rx_data call later in this function may cause
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * deadlock during fault injections. Instead remove
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * the cmd from the active queue and release the locks.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Then before returning or completing the command
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * return the cmd to the active queue and reacquire
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * the locks.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_dequeue_active_cmd(icp, icmdp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&icp->conn_queue_active.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* shorthand some values */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bp = icmdp->cmd_un.scsi.bp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * some poorly behaved targets have been observed
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * sending data-in pdu's during a write operation
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (bp != NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (!(bp->b_flags & B_READ)) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap cmn_err(CE_WARN,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "iscsi connection(%u) protocol error - "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "received data response during write operation "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "itt:0x%x",
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icp->conn_oid, idrhp->itt);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_enter(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_enqueue_active_cmd(icp, icmdp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_PROTOCOL_ERROR);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ibp = icmdp->cmd_un.scsi.ibp_ibuf;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (ibp == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * After the check of bp above we *should* have a corresponding
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * idm_buf_t (ibp). It's possible that the original call
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * to idm_buf_alloc failed due to a pending connection state
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * transition in which case this value can be NULL. It's
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * highly unlikely that the connection would be shutting down
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * *and* we manage to process a data response and get to this
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * point in the code but just in case we should check for it.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * This isn't really a protocol error -- we are almost certainly
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * closing the connection anyway so just return a generic error.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_enter(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_enqueue_active_cmd(icp, icmdp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_FAIL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (ic->ic_conn_flags & IDM_CONN_USE_SCOREBOARD) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.data_transferred =
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_itp->idt_rx_bytes;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.data_transferred = bp->b_bcount;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (idrhp->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.data_transferred -=
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ntohl(idrhp->residual_count);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISCSI_IO_LOG(CE_NOTE, "DEBUG: rx_process_data_rsp: icp: %p pdu: %p "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "itt: %d ibp: %p icmdp: %p xfer_len: %lu transferred: %lu dlen: %u",
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (void *)icp, (void *)pdu, idrhp->itt, (void *)bp, (void *)icmdp,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (ibp == NULL) ? 0 : ibp->idb_xfer_len,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.data_transferred,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap n2h24(idrhp->dlength));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_task_cleanup(idrhp->opcode, icmdp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_data_rsp_pkt(icmdp, idrhp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_enter(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_enqueue_active_cmd(icp, icmdp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icp->conn_queue_active.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_SUCCESS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_rx_process_nop - Process a received nop. If nop is in response
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to a ping we sent update stats. If initiated by the target we need
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to response back to the target with a nop. Schedule the response.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic idm_status_t
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_rx_process_nop(idm_conn_t *ic, idm_pdu_t *pdu)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_sess_t *isp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_nop_in_hdr_t *inihp = (iscsi_nop_in_hdr_t *)pdu->isp_hdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_t *icmdp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_conn_t *icp = ic->ic_handle;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icp->conn_expstatsn != ntohl(inihp->statsn)) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap cmn_err(CE_WARN, "iscsi connection(%u/%x) protocol error - "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "received status out of order itt:0x%x statsn:0x%x "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "expstatsn:0x%x", icp->conn_oid, inihp->opcode, inihp->itt,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ntohl(inihp->statsn), icp->conn_expstatsn);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_PROTOCOL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap isp = icp->conn_sess;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&isp->sess_queue_pending.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&icp->conn_queue_active.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&isp->sess_cmdsn_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (inihp->itt != ISCSI_RSVD_TASK_TAG) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap isp, (iscsi_hdr_t *)inihp, &icmdp))) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap cmn_err(CE_WARN, "iscsi connection(%u) protocol error "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "- can not find cmd for itt:0x%x",
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icp->conn_oid, inihp->itt);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_cmdsn_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icp->conn_queue_active.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_queue_pending.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_PROTOCOL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* update expcmdsn and maxcmdsn */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_update_flow_control(isp, ntohl(inihp->maxcmdsn),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ntohl(inihp->expcmdsn));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_cmdsn_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((inihp->itt != ISCSI_RSVD_TASK_TAG) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (inihp->ttt == ISCSI_RSVD_TASK_TAG)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* This is the only type of nop that incs. the expstatsn */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icp->conn_expstatsn++;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This is a targets response to our nop
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (inihp->ttt != ISCSI_RSVD_TASK_TAG) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Target requested a nop. Send one.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_handle_nop(icp, ISCSI_RSVD_TASK_TAG, inihp->ttt);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This is a target-initiated ping that doesn't expect
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * a response; nothing to do except update our flow control
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * (which we do in all cases above).
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* EMPTY */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icp->conn_queue_active.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_queue_pending.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_SUCCESS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_rx_process_reject_rsp - The server rejected a PDU
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic idm_status_t
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_rx_process_reject_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_reject_rsp_hdr_t *irrhp = (iscsi_reject_rsp_hdr_t *)pdu->isp_hdr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_sess_t *isp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap uint32_t dlength = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_hdr_t *old_ihp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_conn_t *icp = ic->ic_handle;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap uint8_t *data = pdu->isp_data;
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China idm_status_t status = IDM_STATUS_SUCCESS;
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China int i = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(data != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap isp = icp->conn_sess;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China /*
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China * In RFC3720 section 10.17, this 4 bytes should be all 0xff.
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China */
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China for (i = 0; i < 4; i++) {
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China if (irrhp->must_be_ff[i] != 0xff) {
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China return (IDM_STATUS_PROTOCOL_ERROR);
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China }
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China }
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China mutex_enter(&isp->sess_cmdsn_mutex);
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China if (icp->conn_expstatsn == ntohl(irrhp->statsn)) {
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China icp->conn_expstatsn++;
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China } else {
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iscsi connection(%u/%x) protocol error - "
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China "received status out of order statsn:0x%x "
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China "expstatsn:0x%x", icp->conn_oid, irrhp->opcode,
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China ntohl(irrhp->statsn), icp->conn_expstatsn);
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China mutex_exit(&isp->sess_cmdsn_mutex);
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China return (IDM_STATUS_PROTOCOL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China /* update expcmdsn and maxcmdsn */
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China iscsi_update_flow_control(isp, ntohl(irrhp->maxcmdsn),
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China ntohl(irrhp->expcmdsn));
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China mutex_exit(&isp->sess_cmdsn_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* If we don't have the rejected header we can't do anything */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dlength = n2h24(irrhp->dlength);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (dlength < sizeof (iscsi_hdr_t)) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_PROTOCOL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* map old ihp */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte old_ihp = (iscsi_hdr_t *)data;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (irrhp->reason) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ISCSI_REJECT_IMM_CMD_REJECT - Immediate Command Reject
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * too many immediate commands (original cmd can be resent)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_REJECT_IMM_CMD_REJECT:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We have exceeded the server's capacity for outstanding
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * immediate commands. This must be a task management
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * command so try to find it in the abortingqueue and
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * complete it.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!(old_ihp->opcode & ISCSI_OP_IMMEDIATE)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Rejecting IMM but old old_hdr wasn't IMM */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_PROTOCOL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We only send NOP and TASK_MGT as IMM. All other
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * cases should be considered as a protocol error.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (old_ihp->opcode & ISCSI_OPCODE_MASK) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_OP_NOOP_OUT:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * A ping was rejected - treat this like
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ping response. The down side is we
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * didn't get an updated MaxCmdSn.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_OP_SCSI_TASK_MGT_MSG:
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China status =
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China iscsi_rx_process_rejected_tsk_mgt(ic, old_ihp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte default:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) protocol error "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "- received a reject for a command(0x%02x) not "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "sent as an immediate", icp->conn_oid,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte old_ihp->opcode);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = IDM_STATUS_PROTOCOL_ERROR;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * For the rest of the reject cases just use the general
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * hammer of dis/reconnecting. This will resolve all
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * noted issues although could be more graceful.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_REJECT_DATA_DIGEST_ERROR:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_REJECT_CMD_BEFORE_LOGIN:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_REJECT_SNACK_REJECT:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_REJECT_PROTOCOL_ERROR:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_REJECT_CMD_NOT_SUPPORTED:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_REJECT_TASK_IN_PROGRESS:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_REJECT_INVALID_DATA_ACK:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_REJECT_INVALID_PDU_FIELD:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_REJECT_LONG_OPERATION_REJECT:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_REJECT_NEGOTIATION_RESET:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte default:
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iscsi connection(%u/%x) closing connection - "
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China "target requested reason:0x%x",
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China icp->conn_oid, irrhp->opcode, irrhp->reason);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = IDM_STATUS_PROTOCOL_ERROR;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
aefdd1313598221872b3e520302b40e1874f2dc7bing zhao - Sun Microsystems - Beijing China return (status);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_rx_process_rejected_tsk_mgt -
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/* ARGSUSED */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic idm_status_t
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_rx_process_rejected_tsk_mgt(idm_conn_t *ic, iscsi_hdr_t *old_ihp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_sess_t *isp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_cmd_t *icmdp = NULL;
d72ea40e44b64f5cdf1bbf852c8887bbe45b3dbeDan McDonald iscsi_conn_t *icp = ic->ic_handle;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte isp = icp->conn_sess;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(old_ihp != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&icp->conn_queue_active.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&isp->sess_cmdsn_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte isp, old_ihp, &icmdp))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_cmdsn_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_PROTOCOL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_cmdsn_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (icmdp->cmd_type) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_CMD_TYPE_ABORT:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_CMD_TYPE_RESET:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E4,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icp->conn_sess);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* We don't send any other task mgr types */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte default:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(B_FALSE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icp->conn_queue_active.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_SUCCESS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_rx_process_task_mgt_rsp -
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic idm_status_t
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_rx_process_task_mgt_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_sess_t *isp = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_scsi_task_mgt_rsp_hdr_t *istmrhp = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_t *icmdp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_conn_t *icp = ic->ic_handle;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_status_t status = IDM_STATUS_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte isp = icp->conn_sess;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap istmrhp = (iscsi_scsi_task_mgt_rsp_hdr_t *)pdu->isp_hdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if ((status = iscsi_rx_chk(icp, isp, (iscsi_scsi_rsp_hdr_t *)istmrhp,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap &icmdp)) != IDM_STATUS_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (status);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (icmdp->cmd_type) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_CMD_TYPE_ABORT:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_CMD_TYPE_RESET:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (istmrhp->response) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case SCSI_TCP_TM_RESP_COMPLETE:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* success */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_state_machine(icmdp,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ISCSI_CMD_EVENT_E3, isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case SCSI_TCP_TM_RESP_NO_TASK:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If the array no longer knows about
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * an ABORT RTT and we no longer have
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * a parent SCSI command it was just
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * completed, free this ABORT resource.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Otherwise FALLTHRU this will flag a
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * protocol problem.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((icmdp->cmd_type == ISCSI_CMD_TYPE_ABORT) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (icmdp->cmd_un.abort.icmdp == NULL)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_state_machine(icmdp,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ISCSI_CMD_EVENT_E4, isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* FALLTHRU */
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China case SCSI_TCP_TM_RESP_REJECTED:
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China /*
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * If the target rejects our reset task,
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * we should record the response and complete
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * this command with the result.
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China */
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China if (icmdp->cmd_type == ISCSI_CMD_TYPE_RESET) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China icmdp->cmd_un.reset.response =
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China istmrhp->response;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China iscsi_cmd_state_machine(icmdp,
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ISCSI_CMD_EVENT_E3, isp);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China break;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China }
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China /* FALLTHRU */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case SCSI_TCP_TM_RESP_NO_LUN:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case SCSI_TCP_TM_RESP_TASK_ALLEGIANT:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case SCSI_TCP_TM_RESP_NO_FAILOVER:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case SCSI_TCP_TM_RESP_IN_PRGRESS:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte default:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Something is out of sync. Flush
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * active queues and resync the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the connection to try and recover
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to a known state.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = IDM_STATUS_PROTOCOL_ERROR;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte default:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "received a task mgt response for a non-task mgt "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "cmd itt:0x%x type:%d", icp->conn_oid, istmrhp->itt,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_type);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = IDM_STATUS_PROTOCOL_ERROR;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (status);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * iscsi_rx_process_logout_rsp -
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapidm_status_t
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_rx_process_logout_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_conn_t *icp = ic->ic_handle;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_logout_rsp_hdr_t *ilrhp =
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (iscsi_logout_rsp_hdr_t *)pdu->isp_hdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_t *icmdp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_sess_t *isp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_status_t status = IDM_STATUS_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte isp = icp->conn_sess;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icp->conn_expstatsn != ntohl(ilrhp->statsn)) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap cmn_err(CE_WARN, "iscsi connection(%u/%x) protocol error - "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "received status out of order itt:0x%x statsn:0x%x "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "expstatsn:0x%x", icp->conn_oid, ilrhp->opcode, ilrhp->itt,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ntohl(ilrhp->statsn), icp->conn_expstatsn);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_PROTOCOL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&icp->conn_queue_active.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&isp->sess_cmdsn_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ilrhp->itt != ISCSI_RSVD_TASK_TAG) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap isp, (iscsi_hdr_t *)ilrhp, &icmdp))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_cmdsn_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_PROTOCOL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* update expcmdsn and maxcmdsn */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_update_flow_control(isp, ntohl(ilrhp->maxcmdsn),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ntohl(ilrhp->expcmdsn));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_cmdsn_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISCSI_IO_LOG(CE_NOTE,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "DEBUG: iscsi_rx_process_logout_rsp: response: %d",
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ilrhp->response);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (ilrhp->response) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_LOGOUT_CID_NOT_FOUND:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If the target doesn't know about our connection
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * then we can consider our self disconnected.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* FALLTHRU */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_LOGOUT_RECOVERY_UNSUPPORTED:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We don't support ErrorRecovery levels above 0
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * currently so consider this success.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* FALLTHRU */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_LOGOUT_CLEANUP_FAILED:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * per spec. "cleanup failed for various reasons."
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Although those various reasons are undefined.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Not sure what to do here. So fake success,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * which will disconnect the connection.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* FALLTHRU */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_LOGOUT_SUCCESS:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_drop_conn_cleanup(icp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte default:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = IDM_STATUS_PROTOCOL_ERROR;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (status);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * iscsi_rx_process_async_rsp
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic idm_status_t
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_rx_process_async_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_conn_t *icp = ic->ic_handle;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_sess_t *isp = icp->conn_sess;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_status_t rval = IDM_STATUS_SUCCESS;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_task_t *itp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_async_evt_hdr_t *iaehp =
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (iscsi_async_evt_hdr_t *)pdu->isp_hdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icp != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(pdu != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_enter(&isp->sess_cmdsn_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (icp->conn_expstatsn == ntohl(iaehp->statsn)) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icp->conn_expstatsn++;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "received status out of order statsn:0x%x "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "expstatsn:0x%x", icp->conn_oid,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ntohl(iaehp->statsn), icp->conn_expstatsn);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&isp->sess_cmdsn_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_PROTOCOL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&isp->sess_cmdsn_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (iaehp->async_event) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_ASYNC_EVENT_SCSI_EVENT:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * SCSI asynchronous event is reported in
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the sense data. Sense data that accompanies
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the report in the data segment identifies the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * condition. If the target supports SCSI
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * asynchronous events reporting (see [SAM2])
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * as indicated in the stardard INQUIRY data
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * (see [SPC3]), its use may be enabled by
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * parameters in the SCSI control mode page
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * (see [SPC3]).
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * T-10 has removed SCSI asunchronous events
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * from the standard. Although we have seen
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * a couple targets still spending these requests.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Those targets were specifically sending them
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * for notification of a LUN/Volume change
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng * (ex. LUN addition/removal). Fire the enumeration
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng * to handle the change.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) {
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng rw_enter(&isp->sess_state_rwlock, RW_READER);
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng if (isp->sess_state == ISCSI_SESS_STATE_LOGGED_IN) {
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng (void) iscsi_sess_enum_request(isp, B_FALSE,
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng isp->sess_state_event_count);
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng }
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng rw_exit(&isp->sess_state_rwlock);
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_ASYNC_EVENT_REQUEST_LOGOUT:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * We've been asked to logout by the target --
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * we need to treat this differently from a normal logout
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * due to a discovery failure. Normal logouts result in
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * an N3 event to the session state machine and an offline
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * of the lun. In this case we want to put the connection
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * into "failed" state and generate N5 to the session state
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * machine since the initiator logged out at the target's
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * request. To track this we set a flag indicating we
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * received this async logout request from the tharget
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&icp->conn_state_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icp->conn_async_logout = B_TRUE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icp->conn_state_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States /* Hold is released in iscsi_handle_logout. */
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States idm_conn_hold(ic);
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Target has requested this connection to logout. */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap itp = kmem_zalloc(sizeof (iscsi_task_t), KM_SLEEP);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap itp->t_arg = icp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap itp->t_blocking = B_FALSE;
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng if (ddi_taskq_dispatch(isp->sess_login_taskq,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (void(*)())iscsi_logout_start, itp, DDI_SLEEP) !=
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap DDI_SUCCESS) {
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States idm_conn_rele(ic);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Disconnect if we couldn't dispatch the task */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_ini_conn_disconnect(ic);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_ASYNC_EVENT_DROPPING_CONNECTION:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Target is going to drop our connection.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * param1 - CID which will be dropped.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * param2 - Min time to reconnect.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * param3 - Max time to reconnect.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * For now just let fail as another disconnect.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * MC/S Once we support > 1 connections then
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * we need to check the CID and drop that
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * specific connection.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_conn_set_login_min_max(icp, iaehp->param2,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iaehp->param3);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_ini_conn_disconnect(ic);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_ASYNC_EVENT_DROPPING_ALL_CONNECTIONS:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Target is going to drop ALL connections.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * param2 - Min time to reconnect.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * param3 - Max time to reconnect.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * For now just let fail as anyother disconnect.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * MC/S Once we support more than > 1 connections
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * then we need to drop all connections on the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * session.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_conn_set_login_min_max(icp, iaehp->param2,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iaehp->param3);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_ini_conn_disconnect(ic);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_ASYNC_EVENT_PARAM_NEGOTIATION:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Target requests parameter negotiation
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * on this connection.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The initiator must honor this request. For
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * now we will request a logout. We can't
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * just ignore this or it might force corruption?
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States /* Hold is released in iscsi_handle_logout */
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States idm_conn_hold(ic);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap itp = kmem_zalloc(sizeof (iscsi_task_t), KM_SLEEP);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap itp->t_arg = icp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap itp->t_blocking = B_FALSE;
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng if (ddi_taskq_dispatch(isp->sess_login_taskq,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (void(*)())iscsi_logout_start, itp, DDI_SLEEP) !=
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap DDI_SUCCESS) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Disconnect if we couldn't dispatch the task */
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States idm_conn_rele(ic);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_ini_conn_disconnect(ic);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_ASYNC_EVENT_VENDOR_SPECIFIC:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We currently don't handle any vendor
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * specific async events. So just ignore
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the request.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_ini_conn_disconnect(ic);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte default:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap rval = IDM_STATUS_PROTOCOL_ERROR;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (rval);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_rx_process_text_rsp - processes iSCSI text response. It sets
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the cmd_result field of the command data structure with the actual
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * status value instead of returning the status value. The return value
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * is SUCCESS in order to let iscsi_handle_text control the operation of
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * a text request.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Text requests are a handled a little different than other types of
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iSCSI commands because the initiator sends additional empty text requests
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * in order to obtain the remaining responses required to complete the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * request. iscsi_handle_text controls the operation of text request, while
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_rx_process_text_rsp just process the current response.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic idm_status_t
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_rx_process_text_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_sess_t *isp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_text_rsp_hdr_t *ithp =
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (iscsi_text_rsp_hdr_t *)pdu->isp_hdr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_conn_t *icp = ic->ic_handle;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_t *icmdp = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte boolean_t final = B_FALSE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t data_len;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap uint8_t *data = pdu->isp_data;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_status_t rval;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte isp = icp->conn_sess;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if ((rval = iscsi_rx_chk(icp, isp, (iscsi_scsi_rsp_hdr_t *)ithp,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap &icmdp)) != IDM_STATUS_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (rval);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* update local final response flag */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ithp->flags & ISCSI_FLAG_FINAL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte final = B_TRUE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * validate received TTT value. RFC3720 specifies the following:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * - F bit set to 1 MUST have a reserved TTT value 0xffffffff
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * - F bit set to 0 MUST have a non-reserved TTT value !0xffffffff
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * In addition, the received TTT value must not change between
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * responses of a long text response
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (((final == B_TRUE) && (ithp->ttt != ISCSI_RSVD_TASK_TAG)) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ((final == B_FALSE) && (ithp->ttt == ISCSI_RSVD_TASK_TAG))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_result = ISCSI_STATUS_PROTOCOL_ERROR;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icp->conn_queue_active.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "received text response with invalid flags:0x%x or "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "ttt:0x%x", icp->conn_oid, ithp->flags, ithp->itt);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_PROTOCOL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((icmdp->cmd_un.text.stage == ISCSI_CMD_TEXT_INITIAL_REQ) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (ithp->ttt == ISCSI_RSVD_TASK_TAG) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (final == B_FALSE)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* TTT should have matched reserved value */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_result = ISCSI_STATUS_PROTOCOL_ERROR;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icp->conn_queue_active.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN, "iscsi connection(%u) protocol "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "error - received text response with invalid "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "ttt:0x%x", icp->conn_oid, ithp->ttt);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_PROTOCOL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If this is first response, save away TTT value for later use
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * in a long text request/response sequence
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icmdp->cmd_un.text.stage == ISCSI_CMD_TEXT_INITIAL_REQ) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.text.ttt = ithp->ttt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte data_len = ntoh24(ithp->dlength);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* check whether enough buffer available to copy data */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((icmdp->cmd_un.text.total_rx_len + data_len) >
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.text.buf_len) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.text.total_rx_len += data_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_result = ISCSI_STATUS_DATA_OVERFLOW;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * DATA_OVERFLOW will result in a SUCCESS return so that
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_handle_text can continue to obtain the remaining
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * text response if needed.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte char *buf_data = (icmdp->cmd_un.text.buf +
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.text.offset);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(data, buf_data, data_len);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.text.offset += data_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.text.total_rx_len += data_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_result = ISCSI_STATUS_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(ithp->rsvd4, icmdp->cmd_un.text.lun,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sizeof (icmdp->cmd_un.text.lun));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* update stage */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (final == B_TRUE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_CONTINUATION;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_SUCCESS);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * iscsi_rx_process_scsi_itt_to_icmdp - Lookup itt using IDM to find matching
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * icmdp. Verify itt in hdr and icmdp are the same.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic iscsi_status_t
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_rx_process_scsi_itt_to_icmdp(iscsi_sess_t *isp, idm_conn_t *ic,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_scsi_rsp_hdr_t *ihp, iscsi_cmd_t **icmdp)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_task_t *itp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(isp != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(ihp != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(icmdp != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(mutex_owned(&isp->sess_cmdsn_mutex));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap itp = idm_task_find_and_complete(ic, ihp->itt, ISCSI_INI_TASK_TTT);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (itp == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap cmn_err(CE_WARN, "iscsi session(%u) protocol error - "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "received unknown itt:0x%x - protocol error",
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap isp->sess_oid, ihp->itt);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (ISCSI_STATUS_INTERNAL_ERROR);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap *icmdp = itp->idt_private;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_task_rele(itp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_SUCCESS);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_rx_process_itt_to_icmdp - Lookup itt in the session's
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * cmd table to find matching icmdp. Verify itt in hdr and
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * icmdp are the same.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic iscsi_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_rx_process_itt_to_icmdp(iscsi_sess_t *isp, iscsi_hdr_t *ihp,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_t **icmdp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int cmd_table_idx = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(ihp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(mutex_owned(&isp->sess_cmdsn_mutex));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* try to find an associated iscsi_pkt */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap cmd_table_idx = (ihp->itt - IDM_TASKIDS_MAX) % ISCSI_CMD_TABLE_SIZE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (isp->sess_cmd_table[cmd_table_idx] == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN, "iscsi session(%u) protocol error - "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "received unknown itt:0x%x - protocol error",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte isp->sess_oid, ihp->itt);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* verify itt */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (isp->sess_cmd_table[cmd_table_idx]->cmd_itt != ihp->itt) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN, "iscsi session(%u) received itt:0x%x "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " which is out of sync with itt:0x%x", isp->sess_oid,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ihp->itt, isp->sess_cmd_table[cmd_table_idx]->cmd_itt);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
29e23f3f1db1e39002f9ee21386db9260b784213andrew.rutz@sun.com /* ensure that icmdp is still in Active state */
29e23f3f1db1e39002f9ee21386db9260b784213andrew.rutz@sun.com if (isp->sess_cmd_table[cmd_table_idx]->cmd_state !=
29e23f3f1db1e39002f9ee21386db9260b784213andrew.rutz@sun.com ISCSI_CMD_STATE_ACTIVE) {
29e23f3f1db1e39002f9ee21386db9260b784213andrew.rutz@sun.com cmn_err(CE_WARN, "iscsi session(%u) received itt:0x%x "
29e23f3f1db1e39002f9ee21386db9260b784213andrew.rutz@sun.com "but icmdp (%p) is not in active state",
29e23f3f1db1e39002f9ee21386db9260b784213andrew.rutz@sun.com isp->sess_oid, ihp->itt,
29e23f3f1db1e39002f9ee21386db9260b784213andrew.rutz@sun.com (void *)isp->sess_cmd_table[cmd_table_idx]);
29e23f3f1db1e39002f9ee21386db9260b784213andrew.rutz@sun.com return (ISCSI_STATUS_INTERNAL_ERROR);
29e23f3f1db1e39002f9ee21386db9260b784213andrew.rutz@sun.com }
29e23f3f1db1e39002f9ee21386db9260b784213andrew.rutz@sun.com
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* make sure this is a SCSI cmd */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *icmdp = isp->sess_cmd_table[cmd_table_idx];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_SUCCESS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * | End of protocol receive routines |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * | Beginning of protocol send routines |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_tx_thread - This thread is the driving point for all
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * iSCSI PDUs after login. No PDUs should call idm_pdu_tx()
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * directly they should be funneled through iscsi_tx_thread.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_tx_thread(iscsi_thread_t *thread, void *arg)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_conn_t *icp = (iscsi_conn_t *)arg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_sess_t *isp = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_t *icmdp = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte clock_t tout;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int ret = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte isp = icp->conn_sess;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(thread != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(thread->signature == SIG_ISCSI_THREAD);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte tout = SEC_TO_TICK(1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Transfer icmdps until shutdown by owning session.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte while (ret != 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte isp->sess_window_open = B_TRUE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * While the window is open, there are commands available
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to send and the session state allows those commands to
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * be sent try to transfer them.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&isp->sess_queue_pending.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte while ((isp->sess_window_open == B_TRUE) &&
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng ((icmdp = isp->sess_queue_pending.head) != NULL)) {
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng if (((icmdp->cmd_type != ISCSI_CMD_TYPE_SCSI) &&
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng (ISCSI_CONN_STATE_FULL_FEATURE(icp->conn_state))) ||
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng (icp->conn_state == ISCSI_CONN_STATE_LOGGED_IN)) {
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng /* update command with this connection info */
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng icmdp->cmd_conn = icp;
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng /* attempt to send this command */
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng iscsi_cmd_state_machine(icmdp,
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng ISCSI_CMD_EVENT_E2, isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng ASSERT(!mutex_owned(
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng &isp->sess_queue_pending.mutex));
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng mutex_enter(&isp->sess_queue_pending.mutex);
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng } else {
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng while (icmdp != NULL) {
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng if ((icmdp->cmd_type !=
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng ISCSI_CMD_TYPE_SCSI) &&
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng (ISCSI_CONN_STATE_FULL_FEATURE
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng (icp->conn_state) != B_TRUE)) {
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng icmdp->cmd_misc_flags |=
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng ISCSI_CMD_MISCFLAG_STUCK;
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng } else if (icp->conn_state !=
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng ISCSI_CONN_STATE_LOGGED_IN) {
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng icmdp->cmd_misc_flags |=
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng ISCSI_CMD_MISCFLAG_STUCK;
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng }
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng icmdp = icmdp->cmd_next;
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng }
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng break;
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_queue_pending.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Go to sleep until there is something new
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to process (awoken via cv_boardcast).
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Or the timer goes off.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = iscsi_thread_wait(thread, tout);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_tx_cmd - transfers icmdp across wire as iscsi pdu
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Just prior to sending the command to the networking layer the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * pending queue lock will be dropped. At this point only local
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * resources will be used, not the icmdp. Holding the queue lock
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * across the networking call can lead to a hang. (This is due
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to the the target driver and networking layers competing use
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * of the timeout() resources and the queue lock being held for
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * both sides.) Upon the completion of this command the lock
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * will have been re-acquired.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_tx_cmd(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_status_t rval = ISCSI_STATUS_INTERNAL_ERROR;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* transfer specific command type */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (icmdp->cmd_type) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_CMD_TYPE_SCSI:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rval = iscsi_tx_scsi(isp, icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_CMD_TYPE_NOP:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rval = iscsi_tx_nop(isp, icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_CMD_TYPE_ABORT:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rval = iscsi_tx_abort(isp, icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_CMD_TYPE_RESET:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rval = iscsi_tx_reset(isp, icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_CMD_TYPE_LOGOUT:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rval = iscsi_tx_logout(isp, icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case ISCSI_CMD_TYPE_TEXT:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rval = iscsi_tx_text(isp, icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte default:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap cmn_err(CE_WARN, "iscsi_tx_cmd: invalid cmdtype: %d",
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_type);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(FALSE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(!mutex_owned(&isp->sess_queue_pending.mutex));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (rval);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * a variable length cdb can be up to 16K, but we obviously don't want
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to put that on the stack; go with 200 bytes; if we get something
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * bigger than that we will kmem_alloc a buffer
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#define DEF_CDB_LEN 200
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * given the size of the cdb, return how many bytes the header takes,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * which is the sizeof addl_hdr_t + the CDB size, minus the 16 bytes
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * stored in the basic header, minus sizeof (ahs_extscb)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#define ADDLHDRSZ(x) (sizeof (iscsi_addl_hdr_t) + (x) - \
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte 16 - 4)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_tx_init_hdr(iscsi_sess_t *isp, iscsi_conn_t *icp,
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China iscsi_text_hdr_t *ihp, int opcode, iscsi_cmd_t *icmdp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ihp->opcode = opcode;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ihp->itt = icmdp->cmd_itt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&isp->sess_cmdsn_mutex);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China icmdp->cmd_sn = isp->sess_cmdsn;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ihp->cmdsn = htonl(isp->sess_cmdsn);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte isp->sess_cmdsn++;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_cmdsn_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ihp->expstatsn = htonl(icp->conn_expstatsn);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icp->conn_laststatsn = icp->conn_expstatsn;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_tx_scsi_data(iscsi_cmd_t *icmdp, iscsi_scsi_cmd_hdr_t *ihp,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_conn_t *icp, idm_pdu_t *pdu)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap struct buf *bp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap size_t buflen = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap uint32_t first_burst_length = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap struct scsi_pkt *pkt;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt = icmdp->cmd_un.scsi.pkt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bp = icmdp->cmd_un.scsi.bp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((bp != NULL) && bp->b_bcount) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte buflen = bp->b_bcount;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap first_burst_length =
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icp->conn_params.first_burst_length;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (bp->b_flags & B_READ) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ihp->flags = ISCSI_FLAG_FINAL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * fix problem where OS sends bp (B_READ &
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * b_bcount!=0) for a TUR or START_STOP.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * (comment came from cisco code.)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((pkt->pkt_cdbp[0] != SCMD_TEST_UNIT_READY) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (pkt->pkt_cdbp[0] != SCMD_START_STOP)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ihp->flags |= ISCSI_FLAG_CMD_READ;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ihp->data_length = htonl(buflen);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ihp->flags = ISCSI_FLAG_CMD_WRITE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * FinalBit on the the iSCSI PDU denotes this
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * is the last PDU in the sequence.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * initial_r2t = true means R2T is required
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * for additional PDU, so there will be no more
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * unsolicited PDUs following
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icp->conn_params.initial_r2t) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ihp->flags |= ISCSI_FLAG_FINAL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Check if we should send ImmediateData */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icp->conn_params.immediate_data) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pdu->isp_data =
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (uint8_t *)icmdp->
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap cmd_un.scsi.bp->b_un.b_addr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pdu->isp_datalen = MIN(MIN(buflen,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte first_burst_length),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_conn->conn_params.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte max_xmit_data_seg_len);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * if everything fits immediate, or
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * we can send all burst data immediate
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * (not unsol), set F
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * XXX This doesn't look right -- it's not
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * clear how we can handle transmitting
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * any unsolicited data. It looks like
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * we only support immediate data. So what
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * happens if we don't set ISCSI_FLAG_FINAL?
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap *
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Unless there's magic code somewhere that
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * is sending the remaining PDU's we should
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * simply set ISCSI_FLAG_FINAL and forget
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * about sending unsolicited data. The big
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * win is the immediate data anyway for small
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * PDU's.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if ((pdu->isp_datalen == buflen) ||
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (pdu->isp_datalen == first_burst_length)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ihp->flags |= ISCSI_FLAG_FINAL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hton24(ihp->dlength, pdu->isp_datalen);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* total data transfer length */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ihp->data_length = htonl(buflen);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ihp->flags = ISCSI_FLAG_FINAL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.data_transferred += pdu->isp_datalen;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* XXX How is this different from the code above? */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* will idm send the next data command up to burst length? */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* send the burstlen if we haven't sent immediate data */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* CRM: should idm send difference min(buflen, first_burst) and imm? */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* (MIN(first_burst_length, buflen) - imdata > 0) */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* CRM_LATER: change this to generate unsolicited pdu */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if ((buflen > 0) &&
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ((bp->b_flags & B_READ) == 0) &&
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (icp->conn_params.initial_r2t == 0) &&
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pdu->isp_datalen == 0) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pdu->isp_datalen = MIN(first_burst_length, buflen);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if ((pdu->isp_datalen == buflen) ||
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (pdu->isp_datalen == first_burst_length)) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ihp->flags |= ISCSI_FLAG_FINAL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pdu->isp_data = (uint8_t *)icmdp->cmd_un.scsi.bp->b_un.b_addr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hton24(ihp->dlength, pdu->isp_datalen);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_tx_scsi_init_pkt(iscsi_cmd_t *icmdp, iscsi_scsi_cmd_hdr_t *ihp)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap struct scsi_pkt *pkt;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt = icmdp->cmd_un.scsi.pkt;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_state = (STATE_GOT_BUS | STATE_GOT_TARGET);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_reason = CMD_INCOMPLETE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* tagged queuing */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pkt->pkt_flags & FLAG_HTAG) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ihp->flags |= ISCSI_ATTR_HEAD_OF_QUEUE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (pkt->pkt_flags & FLAG_OTAG) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ihp->flags |= ISCSI_ATTR_ORDERED;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (pkt->pkt_flags & FLAG_STAG) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ihp->flags |= ISCSI_ATTR_SIMPLE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* ihp->flags |= ISCSI_ATTR_UNTAGGED; */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* EMPTY */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* iscsi states lun is based on spc.2 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ISCSI_LUN_BYTE_COPY(ihp->lun, icmdp->cmd_un.scsi.lun);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icmdp->cmd_un.scsi.cmdlen <= 16) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* copy the SCSI Command Block into the PDU */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(pkt->pkt_cdbp, ihp->scb,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.scsi.cmdlen);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_addl_hdr_t *iahp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iahp = (iscsi_addl_hdr_t *)ihp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ihp->hlength = (ADDLHDRSZ(icmdp->cmd_un.scsi.cmdlen) -
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sizeof (iscsi_scsi_cmd_hdr_t) + 3) / 4;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iahp->ahs_hlen_hi = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iahp->ahs_hlen_lo = (icmdp->cmd_un.scsi.cmdlen - 15);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iahp->ahs_key = 0x01;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iahp->ahs_resv = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(pkt->pkt_cdbp, ihp->scb, 16);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bcopy(((char *)pkt->pkt_cdbp) + 16, &iahp->ahs_extscb[0],
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.cmdlen);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Update all values before transfering.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * We should never touch the icmdp after
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * transfering if there is no more data
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * to send. The only case the idm_pdu_tx()
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * will fail is a on a connection disconnect
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * in that case the command will be flushed.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt->pkt_state |= STATE_SENT_CMD;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_tx_scsi_init_task(iscsi_cmd_t *icmdp, iscsi_conn_t *icp,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_scsi_cmd_hdr_t *ihp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_task_t *itp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap struct buf *bp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap uint32_t data_length;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bp = icmdp->cmd_un.scsi.bp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap itp = icmdp->cmd_itp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(itp != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap data_length = ntohl(ihp->data_length);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISCSI_IO_LOG(CE_NOTE,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "DEBUG: iscsi_tx_init_task: task_start: %p idt_tt: %x cmdsn: %x "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "sess_cmdsn: %x cmd: %p "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "cmdtype: %d datalen: %u",
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (void *)itp, itp->idt_tt, ihp->cmdsn, icp->conn_sess->sess_cmdsn,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (void *)icmdp, icmdp->cmd_type, data_length);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (data_length > 0) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (bp->b_flags & B_READ) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.ibp_ibuf =
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_buf_alloc(icp->conn_ic,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bp->b_un.b_addr, bp->b_bcount);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (icmdp->cmd_un.scsi.ibp_ibuf)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_buf_bind_in(itp,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.ibp_ibuf);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.ibp_obuf =
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_buf_alloc(icp->conn_ic,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bp->b_un.b_addr, bp->b_bcount);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (icmdp->cmd_un.scsi.ibp_obuf)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_buf_bind_out(itp,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.ibp_obuf);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISCSI_IO_LOG(CE_NOTE,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "DEBUG: pdu_tx: task_start(%s): %p ic: %p idt_tt: %x "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "cmdsn: %x sess_cmdsn: %x sess_expcmdsn: %x obuf: %p "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "cmdp: %p cmdtype: %d "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "buflen: %lu " "bpaddr: %p datalen: %u ",
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bp->b_flags & B_READ ? "B_READ" : "B_WRITE",
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (void *)itp, (void *)icp->conn_ic,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap itp->idt_tt, ihp->cmdsn,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icp->conn_sess->sess_cmdsn,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icp->conn_sess->sess_expcmdsn,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (void *)icmdp->cmd_un.scsi.ibp_ibuf,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (void *)icmdp, icmdp->cmd_type, bp->b_bcount,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (void *)bp->b_un.b_addr,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap data_length);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Task is now active
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_task_start(itp, ISCSI_INI_TASK_TTT);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * iscsi_tx_scsi -
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic iscsi_status_t
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_tx_scsi(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_conn_t *icp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap struct scsi_pkt *pkt = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_scsi_cmd_hdr_t *ihp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap int cdblen = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_t *pdu;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap int len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pdu = kmem_zalloc(sizeof (idm_pdu_t), KM_SLEEP);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pkt = icmdp->cmd_un.scsi.pkt;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(pkt != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icp = icmdp->cmd_conn;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(icp != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Reset counts in case we are on a retry */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp->cmd_un.scsi.data_transferred = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (icmdp->cmd_un.scsi.cmdlen > DEF_CDB_LEN) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap cdblen = icmdp->cmd_un.scsi.cmdlen;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ihp = kmem_zalloc(ADDLHDRSZ(cdblen), KM_SLEEP);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap len = ADDLHDRSZ(cdblen);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * only bzero the basic header; the additional header
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * will be set up correctly later, if needed
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ihp = kmem_zalloc(sizeof (iscsi_scsi_cmd_hdr_t), KM_SLEEP);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap len = sizeof (iscsi_scsi_cmd_hdr_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_tx_init_hdr(isp, icp, (iscsi_text_hdr_t *)ihp,
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ISCSI_OP_SCSI_CMD, icmdp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_init(pdu, icp->conn_ic, (void *)icmdp, &iscsi_tx_done);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_init_hdr(pdu, (uint8_t *)ihp, len);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pdu->isp_data = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pdu->isp_datalen = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Sestion 12.11 of the iSCSI specification has a good table
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * describing when uncolicited data and/or immediate data
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * should be sent.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_tx_scsi_data(icmdp, ihp, icp, pdu);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_tx_scsi_init_pkt(icmdp, ihp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Calls idm_task_start */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_tx_scsi_init_task(icmdp, icp, ihp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_queue_pending.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_tx(pdu);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China icmdp->cmd_misc_flags |= ISCSI_CMD_MISCFLAG_SENT;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (rval);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/* ARGSUSED */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_tx_done(idm_pdu_t *pdu, idm_status_t status)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap kmem_free((iscsi_hdr_t *)pdu->isp_hdr, pdu->isp_hdrlen);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap kmem_free(pdu, sizeof (idm_pdu_t));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_tx_pdu(iscsi_conn_t *icp, int opcode, void *hdr, int hdrlen,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_cmd_t *icmdp)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_t *tx_pdu;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_hdr_t *ihp = (iscsi_hdr_t *)hdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap tx_pdu = kmem_zalloc(sizeof (idm_pdu_t), KM_SLEEP);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(tx_pdu != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_init(tx_pdu, icp->conn_ic, icmdp, &iscsi_tx_done);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_init_hdr(tx_pdu, hdr, hdrlen);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (opcode == ISCSI_OP_TEXT_CMD) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_init_data(tx_pdu,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (uint8_t *)icmdp->cmd_un.text.buf,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ntoh24(ihp->dlength));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&icp->conn_sess->sess_queue_pending.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_tx(tx_pdu);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China icmdp->cmd_misc_flags |= ISCSI_CMD_MISCFLAG_SENT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_tx_nop -
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic iscsi_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_tx_nop(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_conn_t *icp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_nop_out_hdr_t *inohp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icp = icmdp->cmd_conn;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap inohp = kmem_zalloc(sizeof (iscsi_nop_out_hdr_t), KM_SLEEP);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(inohp != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap inohp->opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap inohp->flags = ISCSI_FLAG_FINAL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap inohp->itt = icmdp->cmd_itt;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap inohp->ttt = icmdp->cmd_ttt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&isp->sess_cmdsn_mutex);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China icmdp->cmd_sn = isp->sess_cmdsn;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap inohp->cmdsn = htonl(isp->sess_cmdsn);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_cmdsn_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap inohp->expstatsn = htonl(icp->conn_expstatsn);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icp->conn_laststatsn = icp->conn_expstatsn;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_tx_pdu(icp, ISCSI_OP_NOOP_OUT, inohp,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap sizeof (iscsi_nop_out_hdr_t), icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (rval);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_tx_abort -
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic iscsi_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_tx_abort(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_conn_t *icp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_scsi_task_mgt_hdr_t *istmh;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icp = icmdp->cmd_conn;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap istmh = kmem_zalloc(sizeof (iscsi_scsi_task_mgt_hdr_t), KM_SLEEP);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(istmh != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&isp->sess_cmdsn_mutex);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China icmdp->cmd_sn = isp->sess_cmdsn;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap istmh->cmdsn = htonl(isp->sess_cmdsn);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_cmdsn_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap istmh->expstatsn = htonl(icp->conn_expstatsn);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icp->conn_laststatsn = icp->conn_expstatsn;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap istmh->itt = icmdp->cmd_itt;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap istmh->opcode = ISCSI_OP_SCSI_TASK_MGT_MSG | ISCSI_OP_IMMEDIATE;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap istmh->function = ISCSI_FLAG_FINAL | ISCSI_TM_FUNC_ABORT_TASK;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISCSI_LUN_BYTE_COPY(istmh->lun,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.abort.icmdp->cmd_un.scsi.lun);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap istmh->rtt = icmdp->cmd_un.abort.icmdp->cmd_itt;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_tx_pdu(icp, ISCSI_OP_SCSI_TASK_MGT_MSG, istmh,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap sizeof (iscsi_scsi_task_mgt_hdr_t), icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (rval);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_tx_reset -
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic iscsi_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_tx_reset(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_conn_t *icp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_scsi_task_mgt_hdr_t *istmh;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icp = icmdp->cmd_conn;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap istmh = kmem_zalloc(sizeof (iscsi_scsi_task_mgt_hdr_t), KM_SLEEP);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(istmh != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap istmh->opcode = ISCSI_OP_SCSI_TASK_MGT_MSG | ISCSI_OP_IMMEDIATE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&isp->sess_cmdsn_mutex);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China icmdp->cmd_sn = isp->sess_cmdsn;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap istmh->cmdsn = htonl(isp->sess_cmdsn);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_cmdsn_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap istmh->expstatsn = htonl(icp->conn_expstatsn);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap istmh->itt = icmdp->cmd_itt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (icmdp->cmd_un.reset.level) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case RESET_LUN:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap istmh->function = ISCSI_FLAG_FINAL |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ISCSI_TM_FUNC_LOGICAL_UNIT_RESET;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISCSI_LUN_BYTE_COPY(istmh->lun, icmdp->cmd_lun->lun_num);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case RESET_TARGET:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case RESET_BUS:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap istmh->function = ISCSI_FLAG_FINAL |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ISCSI_TM_FUNC_TARGET_WARM_RESET;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte default:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* unsupported / unknown level */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(FALSE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_tx_pdu(icp, ISCSI_OP_SCSI_TASK_MGT_MSG, istmh,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap sizeof (iscsi_scsi_task_mgt_hdr_t), icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (rval);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_tx_logout -
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic iscsi_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_tx_logout(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_conn_t *icp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_logout_hdr_t *ilh;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icp = icmdp->cmd_conn;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ilh = kmem_zalloc(sizeof (iscsi_logout_hdr_t), KM_SLEEP);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ilh->opcode = ISCSI_OP_LOGOUT_CMD | ISCSI_OP_IMMEDIATE;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ilh->flags = ISCSI_FLAG_FINAL | ISCSI_LOGOUT_REASON_CLOSE_SESSION;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ilh->itt = icmdp->cmd_itt;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ilh->cid = icp->conn_cid;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&isp->sess_cmdsn_mutex);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China icmdp->cmd_sn = isp->sess_cmdsn;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ilh->cmdsn = htonl(isp->sess_cmdsn);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_cmdsn_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ilh->expstatsn = htonl(icp->conn_expstatsn);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_tx_pdu(icp, ISCSI_OP_LOGOUT_CMD, ilh,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap sizeof (iscsi_logout_hdr_t), icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (rval);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_tx_text - setup iSCSI text request header and send PDU with
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * data given in the buffer attached to the command. For a single
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * text request, the target may need to send its response in multiple
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * text response. In this case, empty text requests are sent after
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * each received response to notify the target the initiator is ready
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * for more response. For the initial request, the data_len field in
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the text specific portion of a command is set to the amount of data
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the initiator wants to send as part of the request. If additional
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * empty text requests are required for long responses, the data_len
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * field is set to 0 by the iscsi_handle_text function.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic iscsi_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_tx_text(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_conn_t *icp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_text_hdr_t *ith;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icp = icmdp->cmd_conn;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ith = kmem_zalloc(sizeof (iscsi_text_hdr_t), KM_SLEEP);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(ith != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ith->flags = ISCSI_FLAG_FINAL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hton24(ith->dlength, icmdp->cmd_un.text.data_len);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ith->ttt = icmdp->cmd_un.text.ttt;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_tx_init_hdr(isp, icp, (iscsi_text_hdr_t *)ith,
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ISCSI_OP_TEXT_CMD, icmdp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bcopy(icmdp->cmd_un.text.lun, ith->rsvd4, sizeof (ith->rsvd4));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_tx_pdu(icp, ISCSI_OP_TEXT_CMD, ith, sizeof (iscsi_text_hdr_t),
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (rval);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * | End of protocol send routines |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_handle_abort -
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_handle_abort(void *arg)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_sess_t *isp = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_t *icmdp = (iscsi_cmd_t *)arg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_t *new_icmdp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_conn_t *icp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icp = icmdp->cmd_conn;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte isp = icp->conn_sess;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* there should only be one abort */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp->cmd_un.scsi.abort_icmdp == NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte new_icmdp = iscsi_cmd_alloc(icp, KM_SLEEP);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China new_icmdp->cmd_type = ISCSI_CMD_TYPE_ABORT;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China new_icmdp->cmd_lun = icmdp->cmd_lun;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China new_icmdp->cmd_un.abort.icmdp = icmdp;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China new_icmdp->cmd_conn = icmdp->cmd_conn;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China icmdp->cmd_un.scsi.abort_icmdp = new_icmdp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* pending queue mutex is already held by timeout_checks */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_state_machine(new_icmdp, ISCSI_CMD_EVENT_E1, isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Callback from IDM indicating that the task has been suspended or aborted.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapvoid
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_task_aborted(idm_task_t *idt, idm_status_t status)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_cmd_t *icmdp = idt->idt_private;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_conn_t *icp = icmdp->cmd_conn;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_sess_t *isp = icp->conn_sess;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(icmdp->cmd_conn != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap switch (status) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap case IDM_STATUS_SUSPENDED:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * If the task is suspended, it may be aborted later,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * so we can ignore this notification.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap break;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap case IDM_STATUS_ABORTED:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_enter(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E9, isp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&icp->conn_queue_active.mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap break;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap default:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Unexpected status.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(0);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_handle_nop -
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_handle_nop(iscsi_conn_t *icp, uint32_t itt, uint32_t ttt)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_sess_t *isp = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_t *icmdp = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte isp = icp->conn_sess;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp = iscsi_cmd_alloc(icp, KM_NOSLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icmdp == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_type = ISCSI_CMD_TYPE_NOP;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_itt = itt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_ttt = ttt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_lun = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icp->conn_nop_lbolt = ddi_get_lbolt();
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * iscsi_handle_reset - send reset request to the target
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_handle_reset(iscsi_sess_t *isp, int level, iscsi_lun_t *ilp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_conn_t *icp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_t icmd;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China if (level == RESET_LUN) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ASSERT(ilp != NULL);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China if (ilp->lun_state & ISCSI_LUN_STATE_BUSY) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China rw_exit(&isp->sess_lun_list_rwlock);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China return (ISCSI_STATUS_SUCCESS);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China }
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ilp->lun_state |= ISCSI_LUN_STATE_BUSY;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China rw_exit(&isp->sess_lun_list_rwlock);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China } else {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China mutex_enter(&isp->sess_reset_mutex);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China if (isp->sess_reset_in_progress == B_TRUE) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China /*
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * If the reset is in progress, it is unnecessary
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * to send reset to the target redunantly.
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China */
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China mutex_exit(&isp->sess_reset_mutex);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China return (ISCSI_STATUS_SUCCESS);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China }
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China isp->sess_reset_in_progress = B_TRUE;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China mutex_exit(&isp->sess_reset_mutex);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China }
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bzero(&icmd, sizeof (iscsi_cmd_t));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmd.cmd_sig = ISCSI_SIG_CMD;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmd.cmd_state = ISCSI_CMD_STATE_FREE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmd.cmd_type = ISCSI_CMD_TYPE_RESET;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmd.cmd_lun = ilp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmd.cmd_un.reset.level = level;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmd.cmd_result = ISCSI_STATUS_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmd.cmd_completed = B_FALSE;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China icmd.cmd_un.reset.response = SCSI_TCP_TM_RESP_COMPLETE;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_init(&icmd.cmd_mutex, NULL, MUTEX_DRIVER, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cv_init(&icmd.cmd_completion, NULL, CV_DRIVER, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If we received an IO and we are not in the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * LOGGED_IN state we are in the process of
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * failing. Just respond that we are BUSY.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng rw_enter(&isp->sess_state_rwlock, RW_READER);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!ISCSI_SESS_STATE_FULL_FEATURE(isp->sess_state)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* We aren't connected to the target fake success */
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng rw_exit(&isp->sess_state_rwlock);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China if (level == RESET_LUN) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ilp->lun_state &= ~ISCSI_LUN_STATE_BUSY;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China rw_exit(&isp->sess_lun_list_rwlock);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China } else {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China mutex_enter(&isp->sess_reset_mutex);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China isp->sess_reset_in_progress = B_FALSE;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China mutex_exit(&isp->sess_reset_mutex);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China }
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_SUCCESS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&isp->sess_queue_pending.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_state_machine(&icmd, ISCSI_CMD_EVENT_E1, isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_queue_pending.mutex);
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng rw_exit(&isp->sess_state_rwlock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* stall until completed */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&icmd.cmd_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte while (icmd.cmd_completed == B_FALSE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cv_wait(&icmd.cmd_completion, &icmd.cmd_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icmd.cmd_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* copy rval */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rval = icmd.cmd_result;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (rval == ISCSI_STATUS_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Reset was successful. We need to flush
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * all active IOs.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icp = isp->sess_conn_list;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte while (icp != NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_t *t_icmdp = NULL;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China iscsi_cmd_t *next_icmdp = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&icp->conn_queue_active.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte t_icmdp = icp->conn_queue_active.head;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte while (t_icmdp != NULL) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China next_icmdp = t_icmdp->cmd_next;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China mutex_enter(&t_icmdp->cmd_mutex);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China if (!(t_icmdp->cmd_misc_flags &
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ISCSI_CMD_MISCFLAG_SENT)) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China /*
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * Although this command is in the
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * active queue, it has not been sent.
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * Skip it.
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China */
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China mutex_exit(&t_icmdp->cmd_mutex);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China t_icmdp = next_icmdp;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China continue;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China }
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China if (level == RESET_LUN) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China if (icmd.cmd_lun == NULL ||
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China t_icmdp->cmd_lun == NULL ||
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China (icmd.cmd_lun->lun_num !=
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China t_icmdp->cmd_lun->lun_num)) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China mutex_exit(&t_icmdp->cmd_mutex);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China t_icmdp = next_icmdp;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China continue;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China }
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China }
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China if (icmd.cmd_sn == t_icmdp->cmd_sn) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China /*
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * This command may be replied with
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * UA sense key later. So currently
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * it is not a suitable time to flush
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * it. Mark its flag with FLUSH. There
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * is no harm to keep it for a while.
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China */
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China t_icmdp->cmd_misc_flags |=
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ISCSI_CMD_MISCFLAG_FLUSH;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China if (t_icmdp->cmd_type ==
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ISCSI_CMD_TYPE_SCSI) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China t_icmdp->cmd_un.scsi.pkt_stat |=
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China STAT_BUS_RESET;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China }
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China mutex_exit(&t_icmdp->cmd_mutex);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China } else if ((icmd.cmd_sn > t_icmdp->cmd_sn) ||
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ((t_icmdp->cmd_sn - icmd.cmd_sn) >
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ISCSI_CMD_SN_WRAP)) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China /*
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * This reset request must act on all
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * the commnds from the same session
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * having a CmdSN lower than the task
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * mangement CmdSN. So flush these
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * commands here.
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China */
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China if (t_icmdp->cmd_type ==
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ISCSI_CMD_TYPE_SCSI) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China t_icmdp->cmd_un.scsi.pkt_stat |=
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China STAT_BUS_RESET;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China }
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China mutex_exit(&t_icmdp->cmd_mutex);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China iscsi_cmd_state_machine(t_icmdp,
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ISCSI_CMD_EVENT_E7, isp);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China } else {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China mutex_exit(&t_icmdp->cmd_mutex);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China }
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China t_icmdp = next_icmdp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icp->conn_queue_active.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icp = icp->conn_next;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rw_exit(&isp->sess_conn_list_rwlock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* clean up */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cv_destroy(&icmd.cmd_completion);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_destroy(&icmd.cmd_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China if (level == RESET_LUN) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ilp->lun_state &= ~ISCSI_LUN_STATE_BUSY;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China rw_exit(&isp->sess_lun_list_rwlock);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China } else {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China mutex_enter(&isp->sess_reset_mutex);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China isp->sess_reset_in_progress = B_FALSE;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China mutex_exit(&isp->sess_reset_mutex);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China }
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (rval);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States * iscsi_logout_start - task handler for deferred logout
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States * Acquire a hold before call, released in iscsi_handle_logout
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_logout_start(void *arg)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_task_t *itp = (iscsi_task_t *)arg;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_conn_t *icp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icp = (iscsi_conn_t *)itp->t_arg;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_enter(&icp->conn_state_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (void) iscsi_handle_logout(icp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&icp->conn_state_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_handle_logout - This function will issue a logout for
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the session from a specific connection.
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States * Acquire idm_conn_hold before call. Released internally.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_handle_logout(iscsi_conn_t *icp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_sess_t *isp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_conn_t *ic;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_t *icmdp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int rval;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte isp = icp->conn_sess;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ic = icp->conn_ic;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp->sess_hba != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(mutex_owned(&icp->conn_state_mutex));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States * If the connection has already gone down (e.g. if the transport
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States * failed between when this LOGOUT was generated and now) then we
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States * can and must skip sending the LOGOUT. Check the same condition
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States * we use below to determine that connection has "settled".
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States if ((icp->conn_state == ISCSI_CONN_STATE_FREE) ||
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States (icp->conn_state == ISCSI_CONN_STATE_FAILED) ||
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States (icp->conn_state == ISCSI_CONN_STATE_POLLING)) {
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States idm_conn_rele(ic);
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States return (0);
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp = iscsi_cmd_alloc(icp, KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_type = ISCSI_CMD_TYPE_LOGOUT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_result = ISCSI_STATUS_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_completed = B_FALSE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&isp->sess_queue_pending.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_queue_pending.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * release connection state mutex to avoid a deadlock. This
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * function is called from within the connection state
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * machine with the lock held. When the logout response is
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * received another call to the connection state machine
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * occurs which causes the deadlock
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icp->conn_state_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* stall until completed */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&icmdp->cmd_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte while (icmdp->cmd_completed == B_FALSE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cv_wait(&icmdp->cmd_completion, &icmdp->cmd_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icmdp->cmd_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&icp->conn_state_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* copy rval */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rval = icmdp->cmd_result;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* clean up */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_free(icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (rval != 0) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* If the logout failed then drop the connection */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_ini_conn_disconnect(icp->conn_ic);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* stall until connection settles */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap while ((icp->conn_state != ISCSI_CONN_STATE_FREE) &&
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (icp->conn_state != ISCSI_CONN_STATE_FAILED) &&
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (icp->conn_state != ISCSI_CONN_STATE_POLLING)) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* wait for transition */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap cv_wait(&icp->conn_state_change, &icp->conn_state_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_conn_rele(ic);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Return value reflects whether the logout command completed --
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * regardless of the return value the connection is closed and
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * ready for reconnection.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (rval);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_handle_text - main control function for iSCSI text requests. This
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * function handles allocating the command, sending initial text request, and
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * handling long response sequence.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If a data overflow condition occurs, iscsi_handle_text continues to
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * receive responses until the all data has been recieved. This allows
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the full data length to be returned to the caller.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_handle_text(iscsi_conn_t *icp, char *buf, uint32_t buf_len,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t data_len, uint32_t *rx_data_len)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_sess_t *isp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_t *icmdp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(buf != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(rx_data_len != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte isp = icp->conn_sess;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Ensure data for text request command is not greater
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * than the negotiated maximum receive data seqment length.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Although iSCSI allows for long text requests (multiple
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * pdus), this function places a restriction on text
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * requests to ensure it is handled by a single PDU.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (data_len > icp->conn_params.max_xmit_data_seg_len) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_CMD_FAILED);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp = iscsi_cmd_alloc(icp, KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_type = ISCSI_CMD_TYPE_TEXT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_result = ISCSI_STATUS_SUCCESS;
d233de7e52b23edf30b2270f51e28cda6e08a98cJack Meng icmdp->cmd_misc_flags &= ~ISCSI_CMD_MISCFLAG_FREE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_completed = B_FALSE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.text.buf = buf;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.text.buf_len = buf_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.text.offset = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.text.data_len = data_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.text.total_rx_len = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.text.ttt = ISCSI_RSVD_TASK_TAG;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_INITIAL_REQ;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortelong_text_response:
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng rw_enter(&isp->sess_state_rwlock, RW_READER);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!ISCSI_SESS_STATE_FULL_FEATURE(isp->sess_state)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_free(icmdp);
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng rw_exit(&isp->sess_state_rwlock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_NO_CONN_LOGGED_IN);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&isp->sess_queue_pending.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_queue_pending.mutex);
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng rw_exit(&isp->sess_state_rwlock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* stall until completed */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&icmdp->cmd_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte while (icmdp->cmd_completed == B_FALSE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cv_wait(&icmdp->cmd_completion, &icmdp->cmd_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icmdp->cmd_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * check if error occured. If data overflow occured, continue on
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to ensure we get all data so that the full data length can be
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * returned to the user
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((icmdp->cmd_result != ISCSI_STATUS_SUCCESS) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (icmdp->cmd_result != ISCSI_STATUS_DATA_OVERFLOW)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_NOTE, "iscsi: SendTarget discovery failed (%d)",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_result);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rval = icmdp->cmd_result;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_free(icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (rval);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* check if this was a partial text PDU */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icmdp->cmd_un.text.stage != ISCSI_CMD_TEXT_FINAL_RSP) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If a paritial text rexponse received, send an empty
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * text request. This follows the behaviour specified
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * in RFC3720 regarding long text responses.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
d233de7e52b23edf30b2270f51e28cda6e08a98cJack Meng icmdp->cmd_misc_flags &= ~ISCSI_CMD_MISCFLAG_FREE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_completed = B_FALSE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.text.data_len = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_CONTINUATION;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte goto long_text_response;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * set total received data length. If data overflow this would be
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * amount of data that would have been received if buffer large
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * enough.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *rx_data_len = icmdp->cmd_un.text.total_rx_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* copy rval */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rval = icmdp->cmd_result;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* clean up */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_free(icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (rval);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_handle_passthru - This function is used to send a uscsi_cmd
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to a specific target lun. This routine is used for internal purposes
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * during enumeration and via the ISCSI_USCSICMD IOCTL. We restrict
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the CDBs that can be issued to a target/lun to INQUIRY, REPORT_LUNS,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and READ_CAPACITY for security purposes.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The logic here is broken into three phases.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * 1) Allocate and initialize a pkt/icmdp
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * 2) Send the pkt/icmdp
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * 3) cv_wait for completion
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_handle_passthru(iscsi_sess_t *isp, uint16_t lun, struct uscsi_cmd *ucmdp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik iscsi_status_t rval;
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik iscsi_cmd_t *icmdp;
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik struct scsi_pkt *pkt;
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik struct buf *bp;
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik struct scsi_arq_status *arqstat;
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik int statuslen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(ucmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ucmdp->uscsi_rqlen > SENSE_LENGTH) {
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik /*
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik * The caller provided sense buffer large enough for additional
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik * sense bytes. We need to allocate pkt_scbp to fit them there
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik * too.
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik */
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik statuslen = ucmdp->uscsi_rqlen + ISCSI_ARQ_STATUS_NOSENSE_LEN;
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik } else {
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik /* The default size of pkt_scbp */
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik statuslen = sizeof (struct scsi_arq_status);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Step 1. Setup structs - KM_SLEEP will always succeed
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bp = kmem_zalloc(sizeof (struct buf), KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(bp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pkt = kmem_zalloc(sizeof (struct scsi_pkt), KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(pkt != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp = iscsi_cmd_alloc(NULL, KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* setup bp structure */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bp->b_flags = B_READ;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bp->b_bcount = ucmdp->uscsi_buflen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bp->b_un.b_addr = ucmdp->uscsi_bufaddr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* setup scsi_pkt structure */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pkt->pkt_ha_private = icmdp;
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik pkt->pkt_scbp = kmem_zalloc(statuslen, KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pkt->pkt_cdbp = kmem_zalloc(ucmdp->uscsi_cdblen, KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* callback routine for passthru, will wake cv_wait */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pkt->pkt_comp = iscsi_handle_passthru_callback;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pkt->pkt_time = ucmdp->uscsi_timeout;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* setup iscsi_cmd structure */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_lun = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_type = ISCSI_CMD_TYPE_SCSI;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.scsi.lun = lun;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.scsi.pkt = pkt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.scsi.bp = bp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(ucmdp->uscsi_cdb, pkt->pkt_cdbp, ucmdp->uscsi_cdblen);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_un.scsi.cmdlen = ucmdp->uscsi_cdblen;
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik icmdp->cmd_un.scsi.statuslen = statuslen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_crc_error_seen = B_FALSE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_completed = B_FALSE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_result = ISCSI_STATUS_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Step 2. Push IO onto pending queue. If we aren't in
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * FULL_FEATURE we need to fail the IO.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng rw_enter(&isp->sess_state_rwlock, RW_READER);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!ISCSI_SESS_STATE_FULL_FEATURE(isp->sess_state)) {
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng rw_exit(&isp->sess_state_rwlock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_free(icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(pkt->pkt_cdbp, ucmdp->uscsi_cdblen);
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik kmem_free(pkt->pkt_scbp, statuslen);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(pkt, sizeof (struct scsi_pkt));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(bp, sizeof (struct buf));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_CMD_FAILED);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&isp->sess_queue_pending.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_queue_pending.mutex);
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng rw_exit(&isp->sess_state_rwlock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Step 3. Wait on cv_wait for completion routine
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&icmdp->cmd_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte while (icmdp->cmd_completed == B_FALSE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cv_wait(&icmdp->cmd_completion, &icmdp->cmd_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icmdp->cmd_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* copy rval */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rval = icmdp->cmd_result;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ucmdp->uscsi_resid = pkt->pkt_resid;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* update scsi status */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte arqstat = (struct scsi_arq_status *)pkt->pkt_scbp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ucmdp->uscsi_status = ((char *)&arqstat->sts_status)[0];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* copy request sense buffers if caller gave space */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((ucmdp->uscsi_rqlen > 0) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (ucmdp->uscsi_rqbuf != NULL)) {
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik ASSERT(ucmdp->uscsi_rqlen >= arqstat->sts_rqpkt_resid);
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik ucmdp->uscsi_rqresid = arqstat->sts_rqpkt_resid;
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik bcopy(&arqstat->sts_sensedata, ucmdp->uscsi_rqbuf,
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik ucmdp->uscsi_rqlen - arqstat->sts_rqpkt_resid);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng if ((ucmdp->uscsi_status == STATUS_CHECK) &&
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng ((icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_INTERNAL)) == B_TRUE) {
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng /*
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng * Internal SCSI commands received status
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng */
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng (void) iscsi_decode_sense(
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng (uint8_t *)&arqstat->sts_sensedata, icmdp);
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng }
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* clean up */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_free(icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(pkt->pkt_cdbp, ucmdp->uscsi_cdblen);
146832db19eb2048b216b5dd0ba4424c7d0dfd17Milos Muzik kmem_free(pkt->pkt_scbp, statuslen);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(pkt, sizeof (struct scsi_pkt));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(bp, sizeof (struct buf));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (rval);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_handle_passthru_callback -
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_handle_passthru_callback(struct scsi_pkt *pkt)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_t *icmdp = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(pkt != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp = (iscsi_cmd_t *)pkt->pkt_ha_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&icmdp->cmd_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_completed = B_TRUE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp->cmd_result = ISCSI_STATUS_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cv_broadcast(&icmdp->cmd_completion);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icmdp->cmd_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * IDM callbacks
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapvoid
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_build_hdr(idm_task_t *idm_task, idm_pdu_t *pdu, uint8_t opcode)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_cmd_t *icmdp = idm_task->idt_private;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_conn_t *icp = icmdp->cmd_conn;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_data_hdr_t *ihp = (iscsi_data_hdr_t *)pdu->isp_hdr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_enter(&icmdp->cmd_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (opcode == ISCSI_OP_SCSI_DATA) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap uint32_t data_sn;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap uint32_t lun;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icmdp = idm_task->idt_private;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icp = icmdp->cmd_conn;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ihp->opcode = opcode;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ihp->itt = icmdp->cmd_itt;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ihp->ttt = idm_task->idt_r2t_ttt;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ihp->expstatsn = htonl(icp->conn_expstatsn);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icp->conn_laststatsn = icp->conn_expstatsn;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap data_sn = ntohl(ihp->datasn);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap data_sn++;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap lun = icmdp->cmd_un.scsi.lun;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISCSI_LUN_BYTE_COPY(ihp->lun, lun);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* CRM: upate_flow_control */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISCSI_IO_LOG(CE_NOTE, "DEBUG: iscsi_build_hdr"
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "(ISCSI_OP_SCSI_DATA): task: %p icp: %p ic: %p itt: %x "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "exp: %d data_sn: %d", (void *)idm_task, (void *)icp,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (void *)icp->conn_ic, ihp->itt, icp->conn_expstatsn,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap data_sn);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap cmn_err(CE_WARN, "iscsi_build_hdr: unprocessed build "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "header opcode: %x", opcode);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&icmdp->cmd_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_process_rsp_status(iscsi_sess_t *isp, iscsi_conn_t *icp,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_status_t status)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap switch (status) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap case IDM_STATUS_SUCCESS:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if ((isp->sess_state == ISCSI_SESS_STATE_IN_FLUSH) &&
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (icp->conn_queue_active.count == 0)) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_drop_conn_cleanup(icp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap break;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap case IDM_STATUS_PROTOCOL_ERROR:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap KSTAT_INC_CONN_ERR_PROTOCOL(icp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_drop_conn_cleanup(icp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap break;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap default:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap break;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_drop_conn_cleanup(iscsi_conn_t *icp) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_enter(&icp->conn_state_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_ini_conn_disconnect(icp->conn_ic);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&icp->conn_state_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapvoid
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_rx_error_pdu(idm_conn_t *ic, idm_pdu_t *pdu, idm_status_t status)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_conn_t *icp = (iscsi_conn_t *)ic->ic_handle;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_sess_t *isp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(icp != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap isp = icp->conn_sess;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(isp != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_process_rsp_status(isp, icp, status);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_complete(pdu, status);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapvoid
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_rx_misc_pdu(idm_conn_t *ic, idm_pdu_t *pdu)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_conn_t *icp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_hdr_t *ihp = (iscsi_hdr_t *)pdu->isp_hdr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_sess_t *isp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_status_t status;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icp = ic->ic_handle;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap isp = icp->conn_sess;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap isp->sess_rx_lbolt = icp->conn_rx_lbolt = ddi_get_lbolt();
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap switch (ihp->opcode & ISCSI_OPCODE_MASK) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap case ISCSI_OP_LOGIN_RSP:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = iscsi_rx_process_login_pdu(ic, pdu);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_complete(pdu, status);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap break;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap case ISCSI_OP_LOGOUT_RSP:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = iscsi_rx_process_logout_rsp(ic, pdu);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_complete(pdu, status);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap break;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap case ISCSI_OP_REJECT_MSG:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = iscsi_rx_process_reject_rsp(ic, pdu);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap break;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap case ISCSI_OP_SCSI_TASK_MGT_RSP:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = iscsi_rx_process_task_mgt_rsp(ic, pdu);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_complete(pdu, status);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap break;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap case ISCSI_OP_NOOP_IN:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = iscsi_rx_process_nop(ic, pdu);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_complete(pdu, status);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap break;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap case ISCSI_OP_ASYNC_EVENT:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = iscsi_rx_process_async_rsp(ic, pdu);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap break;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap case ISCSI_OP_TEXT_RSP:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = iscsi_rx_process_text_rsp(ic, pdu);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_complete(pdu, status);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap break;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap default:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap cmn_err(CE_WARN, "iscsi connection(%u) protocol error "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "- received misc unsupported opcode 0x%02x",
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap icp->conn_oid, ihp->opcode);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = IDM_STATUS_PROTOCOL_ERROR;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap break;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_process_rsp_status(isp, icp, status);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * | Beginning of completion routines |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_ic_thread -
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_ic_thread(iscsi_thread_t *thread, void *arg)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_sess_t *isp = (iscsi_sess_t *)arg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int ret;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_queue_t q;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_t *icmdp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_t *next_icmdp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(thread != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(thread->signature == SIG_ISCSI_THREAD);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (;;) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We wait till iodone or somebody else wakes us up.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = iscsi_thread_wait(thread, -1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The value should never be negative since we never timeout.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(ret >= 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte q.count = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte q.head = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte q.tail = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&isp->sess_queue_completion.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp = isp->sess_queue_completion.head;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte while (icmdp != NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte next_icmdp = icmdp->cmd_next;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&icmdp->cmd_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * check if the associated r2t/abort has finished
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * yet. If not, don't complete the command.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((icmdp->cmd_un.scsi.r2t_icmdp == NULL) &&
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (icmdp->cmd_un.scsi.abort_icmdp == NULL)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icmdp->cmd_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) iscsi_dequeue_cmd(&isp->
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sess_queue_completion.head,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte &isp->sess_queue_completion.tail,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte --isp->sess_queue_completion.count;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_enqueue_cmd_head(&q.head,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte &q.tail, icmdp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icmdp->cmd_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp = next_icmdp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_queue_completion.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp = q.head;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte while (icmdp != NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte next_icmdp = icmdp->cmd_next;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E8, isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp = next_icmdp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ret > 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Somebody woke us up to work */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Somebody woke us up to kill ourselves. We will
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * make sure, however that the completion queue is
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * empty before leaving. After we've done that it
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * is the originator of the signal that has to make
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * sure no other SCSI command is posted.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_iodone -
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_iodone(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct scsi_pkt *pkt = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct buf *bp = icmdp->cmd_un.scsi.bp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pkt = icmdp->cmd_un.scsi.pkt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(pkt != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp->cmd_un.scsi.abort_icmdp == NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(icmdp->cmd_un.scsi.r2t_icmdp == NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pkt->pkt_reason == CMD_CMPLT) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (bp) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (bp->b_flags & B_READ) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte KSTAT_SESS_RX_IO_DONE(isp, bp->b_bcount);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte KSTAT_SESS_TX_IO_DONE(isp, bp->b_bcount);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pkt->pkt_flags & FLAG_NOINTR) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cv_broadcast(&icmdp->cmd_completion);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icmdp->cmd_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Release mutex. As soon as callback is
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * issued the caller may destroy the command.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icmdp->cmd_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We can't just directly call the pk_comp routine. In
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * many error cases the target driver will use the calling
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * thread to re-drive error handling (reset, retries...)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * back into the hba driver (iscsi). If the target redrives
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * a reset back into the iscsi driver off this thead we have
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * a chance of deadlocking. So instead use the io completion
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * thread.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (*icmdp->cmd_un.scsi.pkt->pkt_comp)(icmdp->cmd_un.scsi.pkt);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * | End of completion routines |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * | Beginning of watchdog routines |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_watchdog_thread -
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_wd_thread(iscsi_thread_t *thread, void *arg)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_sess_t *isp = (iscsi_sess_t *)arg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int rc = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte while (rc != NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_timeout_checks(isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_nop_checks(isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rc = iscsi_thread_wait(thread, SEC_TO_TICK(1));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_timeout_checks -
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_timeout_checks(iscsi_sess_t *isp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte clock_t now = ddi_get_lbolt();
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_conn_t *icp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_cmd_t *icmdp, *nicmdp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* PENDING */
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng rw_enter(&isp->sess_state_rwlock, RW_READER);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&isp->sess_queue_pending.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (icmdp = isp->sess_queue_pending.head;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp; icmdp = nicmdp) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte nicmdp = icmdp->cmd_next;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Skip entries with no timeout */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icmdp->cmd_lbolt_timeout == 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Skip pending queue entries for cmd_type values that depend
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * on having an open cmdsn window for successfull transition
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * from pending to the active (i.e. ones that depend on
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * sess_cmdsn .vs. sess_maxcmdsn). For them, the timer starts
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * when they are successfully moved to the active queue by
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_cmd_state_pending() code.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
d233de7e52b23edf30b2270f51e28cda6e08a98cJack Meng /*
d233de7e52b23edf30b2270f51e28cda6e08a98cJack Meng * If the cmd is stuck, at least give it a chance
d233de7e52b23edf30b2270f51e28cda6e08a98cJack Meng * to timeout
d233de7e52b23edf30b2270f51e28cda6e08a98cJack Meng */
d233de7e52b23edf30b2270f51e28cda6e08a98cJack Meng if (((icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) ||
d233de7e52b23edf30b2270f51e28cda6e08a98cJack Meng (icmdp->cmd_type == ISCSI_CMD_TYPE_TEXT)) &&
d233de7e52b23edf30b2270f51e28cda6e08a98cJack Meng !(icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_STUCK))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Skip if timeout still in the future */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (now <= icmdp->cmd_lbolt_timeout)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* timeout */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E6, isp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_queue_pending.mutex);
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng rw_exit(&isp->sess_state_rwlock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icp = isp->sess_conn_list;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte while (icp != NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China icp->conn_timeout = B_FALSE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* ACTIVE */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&icp->conn_state_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&isp->sess_queue_pending.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&icp->conn_queue_active.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (icmdp = icp->conn_queue_active.head;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icmdp; icmdp = nicmdp) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte nicmdp = icmdp->cmd_next;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China if (iscsi_nop_timeout_checks(icmdp) == B_TRUE) {
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China icp->conn_timeout = B_TRUE;
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China }
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Skip entries with no timeout */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icmdp->cmd_lbolt_timeout == 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China /*
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * Skip if command is not active or not needed
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * to flush.
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China */
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China if (icmdp->cmd_state != ISCSI_CMD_STATE_ACTIVE &&
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China !(icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_FLUSH))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Skip if timeout still in the future */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (now <= icmdp->cmd_lbolt_timeout)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China if (icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_FLUSH) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China /*
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * This command is left during target reset,
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * we can flush it now.
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China */
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China iscsi_cmd_state_machine(icmdp,
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ISCSI_CMD_EVENT_E7, isp);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China } else if (icmdp->cmd_state == ISCSI_CMD_STATE_ACTIVE) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China /* timeout */
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China iscsi_cmd_state_machine(icmdp,
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ISCSI_CMD_EVENT_E6, isp);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China }
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icp->conn_queue_active.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_queue_pending.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icp->conn_state_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icp = icp->conn_next;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China icp = isp->sess_conn_list;
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China while (icp != NULL) {
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China if (icp->conn_timeout == B_TRUE) {
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China /* timeout on this connect detected */
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China idm_ini_conn_disconnect(icp->conn_ic);
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China icp->conn_timeout = B_FALSE;
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China }
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China icp = icp->conn_next;
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rw_exit(&isp->sess_conn_list_rwlock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_nop_checks - sends a NOP on idle connections
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This function walks the connections on a session and
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * issues NOPs on those connections that are in FULL
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * FEATURE mode and have not received data for the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * time period specified by iscsi_nop_delay (global).
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_nop_checks(iscsi_sess_t *isp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_conn_t *icp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(isp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (isp->sess_type == ISCSI_SESS_TYPE_DISCOVERY) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icp = isp->sess_conn_act;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (icp != NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&icp->conn_state_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((ISCSI_CONN_STATE_FULL_FEATURE(icp->conn_state)) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (ddi_get_lbolt() > isp->sess_conn_act->conn_rx_lbolt +
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte SEC_TO_TICK(iscsi_nop_delay)) && (ddi_get_lbolt() >
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte isp->sess_conn_act->conn_nop_lbolt +
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte SEC_TO_TICK(iscsi_nop_delay))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We haven't received anything from the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * target is a defined period of time,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * send NOP to see if the target is alive.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_enter(&isp->sess_queue_pending.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_handle_nop(isp->sess_conn_act,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte 0, ISCSI_RSVD_TASK_TAG);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&isp->sess_queue_pending.mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_exit(&icp->conn_state_mutex);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte icp = icp->conn_next;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rw_exit(&isp->sess_conn_list_rwlock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing Chinastatic boolean_t
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing Chinaiscsi_nop_timeout_checks(iscsi_cmd_t *icmdp)
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China{
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China if (icmdp->cmd_type == ISCSI_CMD_TYPE_NOP) {
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China if ((ddi_get_lbolt() - icmdp->cmd_lbolt_active) >
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China SEC_TO_TICK(ISCSI_CONN_TIEMOUT_DETECT)) {
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China return (B_TRUE);
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China } else {
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China return (B_FALSE);
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China }
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China }
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China return (B_FALSE);
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * | End of wd routines |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China/*
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * iscsi_flush_cmd_after_reset - flush commands after reset
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China *
b97c1f925a1d211d325cdc3a2e4b3b779082510bMilos Muzik * Here we will flush all the commands for a specified LUN whose cmdsn is less
b97c1f925a1d211d325cdc3a2e4b3b779082510bMilos Muzik * than the one received with the Unit Attention.
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China */
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing Chinastatic void
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing Chinaiscsi_flush_cmd_after_reset(uint32_t cmd_sn, uint16_t lun_num,
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China iscsi_conn_t *icp)
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China{
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China iscsi_cmd_t *t_icmdp = NULL;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China iscsi_cmd_t *next_icmdp = NULL;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ASSERT(icp != NULL);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China t_icmdp = icp->conn_queue_active.head;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China while (t_icmdp != NULL) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China next_icmdp = t_icmdp->cmd_next;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China mutex_enter(&t_icmdp->cmd_mutex);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China /*
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * We will flush the commands whose cmdsn is less than the one
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * got Unit Attention.
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * Here we will check for wrap by subtracting and compare to
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * 1/2 of a 32 bit number, if greater then we wrapped.
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China */
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China if ((t_icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_SENT) &&
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ((cmd_sn > t_icmdp->cmd_sn) ||
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ((t_icmdp->cmd_sn - cmd_sn) >
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ISCSI_CMD_SN_WRAP))) {
b97c1f925a1d211d325cdc3a2e4b3b779082510bMilos Muzik /*
b97c1f925a1d211d325cdc3a2e4b3b779082510bMilos Muzik * Internally generated SCSI commands do not have
b97c1f925a1d211d325cdc3a2e4b3b779082510bMilos Muzik * t_icmdp->cmd_lun set, but the LUN can be retrieved
b97c1f925a1d211d325cdc3a2e4b3b779082510bMilos Muzik * from t_icmdp->cmd_un.scsi.lun.
b97c1f925a1d211d325cdc3a2e4b3b779082510bMilos Muzik */
b97c1f925a1d211d325cdc3a2e4b3b779082510bMilos Muzik if ((t_icmdp->cmd_lun != NULL &&
b97c1f925a1d211d325cdc3a2e4b3b779082510bMilos Muzik t_icmdp->cmd_lun->lun_num == lun_num) ||
b97c1f925a1d211d325cdc3a2e4b3b779082510bMilos Muzik (t_icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI &&
b97c1f925a1d211d325cdc3a2e4b3b779082510bMilos Muzik (t_icmdp->cmd_un.scsi.lun & ISCSI_LUN_MASK) ==
b97c1f925a1d211d325cdc3a2e4b3b779082510bMilos Muzik lun_num)) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China t_icmdp->cmd_misc_flags |=
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ISCSI_CMD_MISCFLAG_FLUSH;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China if (t_icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China t_icmdp->cmd_un.scsi.pkt_stat |=
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China STAT_BUS_RESET;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China }
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China }
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China }
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China mutex_exit(&t_icmdp->cmd_mutex);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China t_icmdp = next_icmdp;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China }
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China}
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China/*
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * iscsi_decode_sense - decode the sense data in the cmd response
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng * and take proper actions
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China */
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing Chinastatic boolean_t
904e51f67bfac9f3ec88d9254757474c448808ebJack Mengiscsi_decode_sense(uint8_t *sense_data, iscsi_cmd_t *icmdp)
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China{
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng uint8_t sense_key = 0;
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng uint8_t asc = 0;
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng uint8_t ascq = 0;
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng boolean_t flush_io = B_FALSE;
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng boolean_t reconfig_lun = B_FALSE;
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng iscsi_sess_t *isp = NULL;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China ASSERT(sense_data != NULL);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng isp = icmdp->cmd_conn->conn_sess;
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China sense_key = scsi_sense_key(sense_data);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China switch (sense_key) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China case KEY_UNIT_ATTENTION:
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China asc = scsi_sense_asc(sense_data);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China switch (asc) {
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China case ISCSI_SCSI_RESET_SENSE_CODE:
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China /*
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * POWER ON, RESET, OR BUS_DEVICE RESET
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * OCCURRED
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China */
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng flush_io = B_TRUE;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China break;
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng case ISCSI_SCSI_LUNCHANGED_CODE:
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng ascq = scsi_sense_ascq(sense_data);
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng if (ascq == ISCSI_SCSI_LUNCHANGED_ASCQ)
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng reconfig_lun = B_TRUE;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China default:
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China break;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China }
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China break;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China default:
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China /*
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * Currently we don't care
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China * about other sense key.
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China */
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China break;
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China }
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng if (reconfig_lun == B_TRUE) {
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng rw_enter(&isp->sess_state_rwlock, RW_READER);
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng if ((isp->sess_state == ISCSI_SESS_STATE_LOGGED_IN) &&
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng (iscsi_sess_enum_request(isp, B_FALSE,
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng isp->sess_state_event_count) !=
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng ISCSI_SESS_ENUM_SUBMITTED)) {
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng cmn_err(CE_WARN, "Unable to commit re-enumeration for"
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng " session(%u) %s", isp->sess_oid, isp->sess_name);
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng }
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng rw_exit(&isp->sess_state_rwlock);
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng }
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng
904e51f67bfac9f3ec88d9254757474c448808ebJack Meng return (flush_io);
2b79d384d32b4ea1e278466cd9b0f3bb56daae22bing zhao - Sun Microsystems - Beijing China}