xref: /onnv-gate/usr/src/uts/common/io/ib/clients/iser/iser_xfer.c (revision 11081:5c9c847827a4)
19162SPeter.Dunlap@Sun.COM /*
29162SPeter.Dunlap@Sun.COM  * CDDL HEADER START
39162SPeter.Dunlap@Sun.COM  *
49162SPeter.Dunlap@Sun.COM  * The contents of this file are subject to the terms of the
59162SPeter.Dunlap@Sun.COM  * Common Development and Distribution License (the "License").
69162SPeter.Dunlap@Sun.COM  * You may not use this file except in compliance with the License.
79162SPeter.Dunlap@Sun.COM  *
89162SPeter.Dunlap@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99162SPeter.Dunlap@Sun.COM  * or http://www.opensolaris.org/os/licensing.
109162SPeter.Dunlap@Sun.COM  * See the License for the specific language governing permissions
119162SPeter.Dunlap@Sun.COM  * and limitations under the License.
129162SPeter.Dunlap@Sun.COM  *
139162SPeter.Dunlap@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
149162SPeter.Dunlap@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159162SPeter.Dunlap@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
169162SPeter.Dunlap@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
179162SPeter.Dunlap@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
189162SPeter.Dunlap@Sun.COM  *
199162SPeter.Dunlap@Sun.COM  * CDDL HEADER END
209162SPeter.Dunlap@Sun.COM  */
219162SPeter.Dunlap@Sun.COM /*
229162SPeter.Dunlap@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
239162SPeter.Dunlap@Sun.COM  * Use is subject to license terms.
249162SPeter.Dunlap@Sun.COM  */
259162SPeter.Dunlap@Sun.COM 
269162SPeter.Dunlap@Sun.COM #include <sys/types.h>
279162SPeter.Dunlap@Sun.COM #include <sys/stat.h>
289162SPeter.Dunlap@Sun.COM #include <sys/conf.h>
299162SPeter.Dunlap@Sun.COM #include <sys/ddi.h>
309162SPeter.Dunlap@Sun.COM #include <sys/sunddi.h>
319162SPeter.Dunlap@Sun.COM #include <sys/modctl.h>
329162SPeter.Dunlap@Sun.COM #include <sys/byteorder.h>
339721SPriya.Krishnan@Sun.COM #include <sys/sdt.h>
349162SPeter.Dunlap@Sun.COM 
359162SPeter.Dunlap@Sun.COM #include <sys/ib/clients/iser/iser.h>
369162SPeter.Dunlap@Sun.COM 
379162SPeter.Dunlap@Sun.COM /*
389162SPeter.Dunlap@Sun.COM  * iser_xfer.c
399162SPeter.Dunlap@Sun.COM  */
409162SPeter.Dunlap@Sun.COM 
419162SPeter.Dunlap@Sun.COM int
iser_xfer_hello_msg(iser_chan_t * chan)429162SPeter.Dunlap@Sun.COM iser_xfer_hello_msg(iser_chan_t *chan)
439162SPeter.Dunlap@Sun.COM {
449162SPeter.Dunlap@Sun.COM 	iser_hca_t		*hca;
459162SPeter.Dunlap@Sun.COM 	iser_wr_t		*iser_wr;
469162SPeter.Dunlap@Sun.COM 	iser_msg_t		*msg;
479162SPeter.Dunlap@Sun.COM 	ibt_send_wr_t		wr;
489162SPeter.Dunlap@Sun.COM 	iser_hello_hdr_t	*hdr;
499162SPeter.Dunlap@Sun.COM 	int			status;
509162SPeter.Dunlap@Sun.COM 
519162SPeter.Dunlap@Sun.COM 	ASSERT(chan != NULL);
529162SPeter.Dunlap@Sun.COM 
539162SPeter.Dunlap@Sun.COM 	hca = (iser_hca_t *)chan->ic_hca;
549162SPeter.Dunlap@Sun.COM 	if (hca == NULL) {
559162SPeter.Dunlap@Sun.COM 		ISER_LOG(CE_NOTE, "iser_xfer_hello_msg: no hca handle found");
569162SPeter.Dunlap@Sun.COM 		return (ISER_STATUS_FAIL);
579162SPeter.Dunlap@Sun.COM 	}
589162SPeter.Dunlap@Sun.COM 
599162SPeter.Dunlap@Sun.COM 	msg = iser_msg_get(hca, 1, NULL);
609162SPeter.Dunlap@Sun.COM 
619162SPeter.Dunlap@Sun.COM 	if (msg == NULL) {
629162SPeter.Dunlap@Sun.COM 		ISER_LOG(CE_NOTE, "iser_xfer_hello_msg: iser message cache "
639162SPeter.Dunlap@Sun.COM 		    "alloc failed");
649162SPeter.Dunlap@Sun.COM 		return (ISER_STATUS_FAIL);
659162SPeter.Dunlap@Sun.COM 	}
669162SPeter.Dunlap@Sun.COM 
679162SPeter.Dunlap@Sun.COM 	/* Send iSER Hello Message to declare iSER parameters to the target */
689162SPeter.Dunlap@Sun.COM 	hdr = (iser_hello_hdr_t *)(uintptr_t)msg->msg_ds.ds_va;
699162SPeter.Dunlap@Sun.COM 
709162SPeter.Dunlap@Sun.COM 	hdr->opcode	= ISER_OPCODE_HELLO_MSG;
719162SPeter.Dunlap@Sun.COM 	hdr->rsvd1	= 0;
729162SPeter.Dunlap@Sun.COM 	hdr->maxver 	= 1;
739162SPeter.Dunlap@Sun.COM 	hdr->minver 	= 1;
749162SPeter.Dunlap@Sun.COM 	hdr->iser_ird 	= htons(ISER_IB_DEFAULT_IRD);
759162SPeter.Dunlap@Sun.COM 	hdr->rsvd2[0] 	= 0;
769162SPeter.Dunlap@Sun.COM 	hdr->rsvd2[1] 	= 0;
779162SPeter.Dunlap@Sun.COM 
789162SPeter.Dunlap@Sun.COM 	/* Allocate an iSER WR handle and tuck this msg into it */
799162SPeter.Dunlap@Sun.COM 	iser_wr = iser_wr_get();
809162SPeter.Dunlap@Sun.COM 	if (iser_wr == NULL) {
819162SPeter.Dunlap@Sun.COM 		ISER_LOG(CE_NOTE, "iser_xfer_hello_msg: unable to allocate "
829162SPeter.Dunlap@Sun.COM 		    "iser wr handle");
839162SPeter.Dunlap@Sun.COM 		iser_msg_free(msg);
849162SPeter.Dunlap@Sun.COM 		return (ISER_STATUS_FAIL);
859162SPeter.Dunlap@Sun.COM 	}
869162SPeter.Dunlap@Sun.COM 	iser_wr->iw_msg = msg;
879162SPeter.Dunlap@Sun.COM 	iser_wr->iw_type = ISER_WR_SEND;
889162SPeter.Dunlap@Sun.COM 
899162SPeter.Dunlap@Sun.COM 	/* Use the address of our generic iser_wr handle as our WRID */
909162SPeter.Dunlap@Sun.COM 	wr.wr_id	= (ibt_wrid_t)(uintptr_t)iser_wr;
919162SPeter.Dunlap@Sun.COM 
929162SPeter.Dunlap@Sun.COM 	/* Populate the rest of the work request */
939162SPeter.Dunlap@Sun.COM 	wr.wr_trans	= IBT_RC_SRV;
949162SPeter.Dunlap@Sun.COM 	wr.wr_opcode	= IBT_WRC_SEND;
959162SPeter.Dunlap@Sun.COM 	wr.wr_nds	= 1;
969162SPeter.Dunlap@Sun.COM 	wr.wr_sgl	= &msg->msg_ds;
979162SPeter.Dunlap@Sun.COM 
9810101SPriya.Krishnan@Sun.COM 	/*
9910101SPriya.Krishnan@Sun.COM 	 * Avoid race condition by incrementing this channel's
10010101SPriya.Krishnan@Sun.COM 	 * SQ posted count prior to calling ibt_post_send
10110101SPriya.Krishnan@Sun.COM 	 */
1029162SPeter.Dunlap@Sun.COM 	mutex_enter(&chan->ic_sq_post_lock);
1039162SPeter.Dunlap@Sun.COM 	chan->ic_sq_post_count++;
1049162SPeter.Dunlap@Sun.COM 	if (chan->ic_sq_post_count > chan->ic_sq_max_post_count)
1059162SPeter.Dunlap@Sun.COM 		chan->ic_sq_max_post_count = chan->ic_sq_post_count;
1069162SPeter.Dunlap@Sun.COM 	mutex_exit(&chan->ic_sq_post_lock);
1079162SPeter.Dunlap@Sun.COM 
10810101SPriya.Krishnan@Sun.COM 	status = ibt_post_send(chan->ic_chanhdl, &wr, 1, NULL);
10910101SPriya.Krishnan@Sun.COM 	if (status != IBT_SUCCESS) {
11010101SPriya.Krishnan@Sun.COM 		ISER_LOG(CE_NOTE, "iser_xfer_hello_msg: ibt_post_send "
11110101SPriya.Krishnan@Sun.COM 		    "failure (%d)", status);
11210101SPriya.Krishnan@Sun.COM 		mutex_enter(&chan->ic_sq_post_lock);
11310101SPriya.Krishnan@Sun.COM 		chan->ic_sq_post_count--;
11410101SPriya.Krishnan@Sun.COM 		mutex_exit(&chan->ic_sq_post_lock);
11510101SPriya.Krishnan@Sun.COM 		iser_msg_free(msg);
11610101SPriya.Krishnan@Sun.COM 		iser_wr_free(iser_wr);
11710101SPriya.Krishnan@Sun.COM 		return (ISER_STATUS_FAIL);
11810101SPriya.Krishnan@Sun.COM 	}
11910101SPriya.Krishnan@Sun.COM 
1209162SPeter.Dunlap@Sun.COM 	ISER_LOG(CE_NOTE, "Posting iSER Hello message: chan (0x%p): "
1219162SPeter.Dunlap@Sun.COM 	    "IP [%x to %x]", (void *)chan, chan->ic_localip.un.ip4addr,
1229162SPeter.Dunlap@Sun.COM 	    chan->ic_remoteip.un.ip4addr);
1239162SPeter.Dunlap@Sun.COM 
1249162SPeter.Dunlap@Sun.COM 	return (ISER_STATUS_SUCCESS);
1259162SPeter.Dunlap@Sun.COM }
1269162SPeter.Dunlap@Sun.COM 
1279162SPeter.Dunlap@Sun.COM int
iser_xfer_helloreply_msg(iser_chan_t * chan)1289162SPeter.Dunlap@Sun.COM iser_xfer_helloreply_msg(iser_chan_t *chan)
1299162SPeter.Dunlap@Sun.COM {
1309162SPeter.Dunlap@Sun.COM 	iser_hca_t		*hca;
1319162SPeter.Dunlap@Sun.COM 	iser_wr_t		*iser_wr;
1329162SPeter.Dunlap@Sun.COM 	ibt_send_wr_t   	wr;
1339162SPeter.Dunlap@Sun.COM 	iser_msg_t		*msg;
1349162SPeter.Dunlap@Sun.COM 	iser_helloreply_hdr_t	*hdr;
1359162SPeter.Dunlap@Sun.COM 	int			status;
1369162SPeter.Dunlap@Sun.COM 
1379162SPeter.Dunlap@Sun.COM 	ASSERT(chan != NULL);
1389162SPeter.Dunlap@Sun.COM 
1399162SPeter.Dunlap@Sun.COM 	hca = (iser_hca_t *)chan->ic_hca;
1409162SPeter.Dunlap@Sun.COM 	if (hca == NULL) {
1419162SPeter.Dunlap@Sun.COM 		ISER_LOG(CE_NOTE, "iser_xfer_helloreply_msg: no hca handle "
1429162SPeter.Dunlap@Sun.COM 		    "found");
1439162SPeter.Dunlap@Sun.COM 		return (ISER_STATUS_FAIL);
1449162SPeter.Dunlap@Sun.COM 	}
1459162SPeter.Dunlap@Sun.COM 
1469162SPeter.Dunlap@Sun.COM 	msg = iser_msg_get(hca, 1, NULL);
1479162SPeter.Dunlap@Sun.COM 
1489162SPeter.Dunlap@Sun.COM 	if (msg == NULL) {
1499162SPeter.Dunlap@Sun.COM 		ISER_LOG(CE_NOTE, "iser_xfer_helloreply_msg: iser message "
1509162SPeter.Dunlap@Sun.COM 		    "cache alloc failed");
1519162SPeter.Dunlap@Sun.COM 		return (ISER_STATUS_FAIL);
1529162SPeter.Dunlap@Sun.COM 	}
1539162SPeter.Dunlap@Sun.COM 
1549162SPeter.Dunlap@Sun.COM 	/* Use the iSER Hello Reply Message */
1559162SPeter.Dunlap@Sun.COM 	hdr = (iser_helloreply_hdr_t *)(uintptr_t)msg->msg_ds.ds_va;
1569162SPeter.Dunlap@Sun.COM 
1579162SPeter.Dunlap@Sun.COM 	hdr->opcode	= ISER_OPCODE_HELLOREPLY_MSG;
1589162SPeter.Dunlap@Sun.COM 	hdr->rsvd1	= 0;
1599162SPeter.Dunlap@Sun.COM 	hdr->flag	= 0;
1609162SPeter.Dunlap@Sun.COM 	hdr->maxver	= 1;
1619162SPeter.Dunlap@Sun.COM 	hdr->curver	= 1;
1629162SPeter.Dunlap@Sun.COM 	hdr->iser_ord	= htons(ISER_IB_DEFAULT_ORD);
1639162SPeter.Dunlap@Sun.COM 	hdr->rsvd2[0]	= 0;
1649162SPeter.Dunlap@Sun.COM 	hdr->rsvd2[1]	= 0;
1659162SPeter.Dunlap@Sun.COM 
1669162SPeter.Dunlap@Sun.COM 	/* Allocate an iSER WR handle and tuck this msg into it */
1679162SPeter.Dunlap@Sun.COM 	iser_wr = iser_wr_get();
1689162SPeter.Dunlap@Sun.COM 	if (iser_wr == NULL) {
1699162SPeter.Dunlap@Sun.COM 		ISER_LOG(CE_NOTE, "iser_xfer_helloreply_msg: unable to "
1709162SPeter.Dunlap@Sun.COM 		    "allocate iser wr handle");
1719162SPeter.Dunlap@Sun.COM 		iser_msg_free(msg);
1729162SPeter.Dunlap@Sun.COM 		return (ISER_STATUS_FAIL);
1739162SPeter.Dunlap@Sun.COM 	}
1749162SPeter.Dunlap@Sun.COM 	iser_wr->iw_msg = msg;
1759162SPeter.Dunlap@Sun.COM 	iser_wr->iw_type = ISER_WR_SEND;
1769162SPeter.Dunlap@Sun.COM 
1779162SPeter.Dunlap@Sun.COM 	/* Use the address of our generic iser_wr handle as our WRID */
1789162SPeter.Dunlap@Sun.COM 	wr.wr_id	= (ibt_wrid_t)(uintptr_t)iser_wr;
1799162SPeter.Dunlap@Sun.COM 
1809162SPeter.Dunlap@Sun.COM 	/* Populate the rest of the work request */
1819162SPeter.Dunlap@Sun.COM 	wr.wr_trans	= IBT_RC_SRV;
1829162SPeter.Dunlap@Sun.COM 	wr.wr_opcode	= IBT_WRC_SEND;
1839162SPeter.Dunlap@Sun.COM 	wr.wr_nds	= 1;
1849162SPeter.Dunlap@Sun.COM 	wr.wr_sgl	= &msg->msg_ds;
1859162SPeter.Dunlap@Sun.COM 
18610101SPriya.Krishnan@Sun.COM 	mutex_enter(&chan->ic_sq_post_lock);
18710101SPriya.Krishnan@Sun.COM 	chan->ic_sq_post_count++;
18810101SPriya.Krishnan@Sun.COM 	if (chan->ic_sq_post_count > chan->ic_sq_max_post_count)
18910101SPriya.Krishnan@Sun.COM 		chan->ic_sq_max_post_count = chan->ic_sq_post_count;
19010101SPriya.Krishnan@Sun.COM 
19110101SPriya.Krishnan@Sun.COM 	mutex_exit(&chan->ic_sq_post_lock);
19210101SPriya.Krishnan@Sun.COM 
1939162SPeter.Dunlap@Sun.COM 	status = ibt_post_send(chan->ic_chanhdl, &wr, 1, NULL);
1949162SPeter.Dunlap@Sun.COM 	if (status != IBT_SUCCESS) {
1959162SPeter.Dunlap@Sun.COM 		ISER_LOG(CE_NOTE, "iser_xfer_helloreply_msg: ibt_post_send "
1969162SPeter.Dunlap@Sun.COM 		    "failure (%d)", status);
19710101SPriya.Krishnan@Sun.COM 		mutex_enter(&chan->ic_sq_post_lock);
19810101SPriya.Krishnan@Sun.COM 		chan->ic_sq_post_count--;
19910101SPriya.Krishnan@Sun.COM 		mutex_exit(&chan->ic_sq_post_lock);
2009162SPeter.Dunlap@Sun.COM 		iser_msg_free(msg);
2019162SPeter.Dunlap@Sun.COM 		iser_wr_free(iser_wr);
2029162SPeter.Dunlap@Sun.COM 		return (ISER_STATUS_FAIL);
2039162SPeter.Dunlap@Sun.COM 	}
2049162SPeter.Dunlap@Sun.COM 	ISER_LOG(CE_NOTE, "Posting iSER HelloReply message: chan (0x%p): "
2059162SPeter.Dunlap@Sun.COM 	    "IP [%x to %x]", (void *)chan, chan->ic_localip.un.ip4addr,
2069162SPeter.Dunlap@Sun.COM 	    chan->ic_remoteip.un.ip4addr);
2079162SPeter.Dunlap@Sun.COM 
2089162SPeter.Dunlap@Sun.COM 	return (ISER_STATUS_SUCCESS);
2099162SPeter.Dunlap@Sun.COM }
2109162SPeter.Dunlap@Sun.COM 
2119162SPeter.Dunlap@Sun.COM /*
2129162SPeter.Dunlap@Sun.COM  * iser_xfer_ctrlpdu
2139162SPeter.Dunlap@Sun.COM  *
2149162SPeter.Dunlap@Sun.COM  * This is iSER's implementation of the 'Send_control' operational primitive.
2159162SPeter.Dunlap@Sun.COM  * This iSER layer uses the Send Message type of RCaP to transfer the iSCSI
2169162SPeter.Dunlap@Sun.COM  * Control-type PDU. A special case is that the transfer of SCSI Data-out PDUs
2179162SPeter.Dunlap@Sun.COM  * carrying unsolicited data are also treated as iSCSI Control-Type PDUs. The
2189162SPeter.Dunlap@Sun.COM  * message payload contains an iSER header followed by the iSCSI Control-type
2199162SPeter.Dunlap@Sun.COM  * the iSCSI Control-type PDU.
2209162SPeter.Dunlap@Sun.COM  * This function is invoked by an initiator iSCSI layer requesting the transfer
2219162SPeter.Dunlap@Sun.COM  * of a iSCSI command PDU or a target iSCSI layer requesting the transfer of a
2229162SPeter.Dunlap@Sun.COM  * iSCSI response PDU.
2239162SPeter.Dunlap@Sun.COM  */
2249162SPeter.Dunlap@Sun.COM int
iser_xfer_ctrlpdu(iser_chan_t * chan,idm_pdu_t * pdu)2259162SPeter.Dunlap@Sun.COM iser_xfer_ctrlpdu(iser_chan_t *chan, idm_pdu_t *pdu)
2269162SPeter.Dunlap@Sun.COM {
2279162SPeter.Dunlap@Sun.COM 	iser_hca_t	*hca;
2289162SPeter.Dunlap@Sun.COM 	iser_ctrl_hdr_t	*hdr;
2299162SPeter.Dunlap@Sun.COM 	iser_msg_t	*msg;
2309162SPeter.Dunlap@Sun.COM 	iser_wr_t	*iser_wr;
2319162SPeter.Dunlap@Sun.COM 	ibt_send_wr_t   wr;
2329162SPeter.Dunlap@Sun.COM 	int		status;
2339162SPeter.Dunlap@Sun.COM 	iser_mr_t	*mr;
2349162SPeter.Dunlap@Sun.COM 	iscsi_data_hdr_t	*bhs;
2359162SPeter.Dunlap@Sun.COM 	idm_conn_t	*ic;
2369162SPeter.Dunlap@Sun.COM 	idm_task_t	*idt = NULL;
2379162SPeter.Dunlap@Sun.COM 	idm_buf_t	*buf;
2389162SPeter.Dunlap@Sun.COM 
2399162SPeter.Dunlap@Sun.COM 	ASSERT(chan != NULL);
2409162SPeter.Dunlap@Sun.COM 
24110101SPriya.Krishnan@Sun.COM 	mutex_enter(&chan->ic_conn->ic_lock);
24210101SPriya.Krishnan@Sun.COM 	/* Bail out if the connection is closed */
24310101SPriya.Krishnan@Sun.COM 	if ((chan->ic_conn->ic_stage == ISER_CONN_STAGE_CLOSING) ||
24410101SPriya.Krishnan@Sun.COM 	    (chan->ic_conn->ic_stage == ISER_CONN_STAGE_CLOSED)) {
24510101SPriya.Krishnan@Sun.COM 		mutex_exit(&chan->ic_conn->ic_lock);
24610101SPriya.Krishnan@Sun.COM 		return (ISER_STATUS_FAIL);
24710101SPriya.Krishnan@Sun.COM 	}
24810101SPriya.Krishnan@Sun.COM 
249*11081SPriya.Krishnan@Sun.COM 	ic = chan->ic_conn->ic_idmc;
250*11081SPriya.Krishnan@Sun.COM 
251*11081SPriya.Krishnan@Sun.COM 	/* Pull the BHS out of the PDU handle */
252*11081SPriya.Krishnan@Sun.COM 	bhs = (iscsi_data_hdr_t *)pdu->isp_hdr;
253*11081SPriya.Krishnan@Sun.COM 
2549162SPeter.Dunlap@Sun.COM 	/*
2559162SPeter.Dunlap@Sun.COM 	 * All SCSI command PDU (except SCSI Read and SCSI Write) and the SCSI
2569162SPeter.Dunlap@Sun.COM 	 * Response PDU are sent to the remote end using the SendSE Message.
2579162SPeter.Dunlap@Sun.COM 	 *
258*11081SPriya.Krishnan@Sun.COM 	 * The StatSN may need to be sent (and possibly advanced) at this time
259*11081SPriya.Krishnan@Sun.COM 	 * for some PDUs, identified by the IDM_PDU_SET_STATSN flag.
260*11081SPriya.Krishnan@Sun.COM 	 */
261*11081SPriya.Krishnan@Sun.COM 	if (pdu->isp_flags & IDM_PDU_SET_STATSN) {
262*11081SPriya.Krishnan@Sun.COM 		(ic->ic_conn_ops.icb_update_statsn)(NULL, pdu);
263*11081SPriya.Krishnan@Sun.COM 	}
264*11081SPriya.Krishnan@Sun.COM 	/*
2659162SPeter.Dunlap@Sun.COM 	 * Setup a Send Message for carrying the iSCSI control-type PDU
2669162SPeter.Dunlap@Sun.COM 	 * preceeded by an iSER header.
2679162SPeter.Dunlap@Sun.COM 	 */
2689162SPeter.Dunlap@Sun.COM 	hca = (iser_hca_t *)chan->ic_hca;
2699162SPeter.Dunlap@Sun.COM 	if (hca == NULL) {
2709162SPeter.Dunlap@Sun.COM 		ISER_LOG(CE_NOTE, "iser_xfer_ctrlpdu: no hca handle found");
27110101SPriya.Krishnan@Sun.COM 		mutex_exit(&chan->ic_conn->ic_lock);
2729162SPeter.Dunlap@Sun.COM 		return (ISER_STATUS_FAIL);
2739162SPeter.Dunlap@Sun.COM 	}
2749162SPeter.Dunlap@Sun.COM 
2759162SPeter.Dunlap@Sun.COM 	msg = iser_msg_get(hca, 1, NULL);
2769162SPeter.Dunlap@Sun.COM 	if (msg == NULL) {
2779162SPeter.Dunlap@Sun.COM 		ISER_LOG(CE_NOTE, "iser_xfer_ctrlpdu: iser message cache "
2789162SPeter.Dunlap@Sun.COM 		    "alloc failed");
27910101SPriya.Krishnan@Sun.COM 		mutex_exit(&chan->ic_conn->ic_lock);
2809162SPeter.Dunlap@Sun.COM 		return (ISER_STATUS_FAIL);
2819162SPeter.Dunlap@Sun.COM 	}
2829162SPeter.Dunlap@Sun.COM 
2839162SPeter.Dunlap@Sun.COM 	hdr = (iser_ctrl_hdr_t *)(uintptr_t)msg->msg_ds.ds_va;
2849162SPeter.Dunlap@Sun.COM 
2859162SPeter.Dunlap@Sun.COM 	/*
2869162SPeter.Dunlap@Sun.COM 	 * Initialize header assuming no transfers
2879162SPeter.Dunlap@Sun.COM 	 */
2889162SPeter.Dunlap@Sun.COM 	bzero(hdr, sizeof (*hdr));
2899162SPeter.Dunlap@Sun.COM 	hdr->opcode	= ISER_OPCODE_CTRL_TYPE_PDU;
2909162SPeter.Dunlap@Sun.COM 
2919162SPeter.Dunlap@Sun.COM 	/*
2929162SPeter.Dunlap@Sun.COM 	 * On the initiator side, the task buffers will be used to identify
2939162SPeter.Dunlap@Sun.COM 	 * if there are any buffers to be advertised
2949162SPeter.Dunlap@Sun.COM 	 */
2959162SPeter.Dunlap@Sun.COM 	if ((ic->ic_conn_type == CONN_TYPE_INI) &&
2969162SPeter.Dunlap@Sun.COM 	    ((bhs->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_SCSI_CMD) &&
2979162SPeter.Dunlap@Sun.COM 	    ((idt = idm_task_find(ic, bhs->itt, bhs->ttt)) != NULL)) {
2989162SPeter.Dunlap@Sun.COM 
2999162SPeter.Dunlap@Sun.COM 		if (!list_is_empty(&idt->idt_inbufv)) {
3009162SPeter.Dunlap@Sun.COM 			buf = idm_buf_find(&idt->idt_inbufv, 0);
3019162SPeter.Dunlap@Sun.COM 			ASSERT(buf != NULL);
3029162SPeter.Dunlap@Sun.COM 
3039162SPeter.Dunlap@Sun.COM 			mr = (iser_mr_t *)buf->idb_reg_private;
3049162SPeter.Dunlap@Sun.COM 			ASSERT(mr != NULL);
3059162SPeter.Dunlap@Sun.COM 
3069162SPeter.Dunlap@Sun.COM 			hdr->rsv_flag = 1;
3079162SPeter.Dunlap@Sun.COM 			hdr->rstag = htonl(mr->is_mrrkey);
3089162SPeter.Dunlap@Sun.COM 			BE_OUT64(&hdr->rva, mr->is_mrva);
3099162SPeter.Dunlap@Sun.COM 		}
3109162SPeter.Dunlap@Sun.COM 
3119162SPeter.Dunlap@Sun.COM 		if (!list_is_empty(&idt->idt_outbufv)) {
3129162SPeter.Dunlap@Sun.COM 			buf = idm_buf_find(&idt->idt_outbufv, 0);
3139162SPeter.Dunlap@Sun.COM 			ASSERT(buf != NULL);
3149162SPeter.Dunlap@Sun.COM 
3159162SPeter.Dunlap@Sun.COM 			mr = (iser_mr_t *)buf->idb_reg_private;
3169162SPeter.Dunlap@Sun.COM 			ASSERT(mr != NULL);
3179162SPeter.Dunlap@Sun.COM 
3189162SPeter.Dunlap@Sun.COM 			hdr->wsv_flag = 1;
3199162SPeter.Dunlap@Sun.COM 			hdr->wstag = htonl(mr->is_mrrkey);
3209162SPeter.Dunlap@Sun.COM 			BE_OUT64(&hdr->wva, mr->is_mrva);
3219162SPeter.Dunlap@Sun.COM 		}
3229162SPeter.Dunlap@Sun.COM 
3239162SPeter.Dunlap@Sun.COM 		/* Release our reference on the task */
3249162SPeter.Dunlap@Sun.COM 		idm_task_rele(idt);
3259162SPeter.Dunlap@Sun.COM 	}
3269162SPeter.Dunlap@Sun.COM 
3279162SPeter.Dunlap@Sun.COM 	/* Copy the BHS after the iSER header */
3289162SPeter.Dunlap@Sun.COM 	bcopy(pdu->isp_hdr,
3299162SPeter.Dunlap@Sun.COM 	    (uint8_t *)(uintptr_t)msg->msg_ds.ds_va + ISER_HEADER_LENGTH,
3309162SPeter.Dunlap@Sun.COM 	    pdu->isp_hdrlen);
3319162SPeter.Dunlap@Sun.COM 
3329162SPeter.Dunlap@Sun.COM 	if (pdu->isp_datalen > 0) {
3339162SPeter.Dunlap@Sun.COM 		/* Copy the isp_data after the PDU header */
3349162SPeter.Dunlap@Sun.COM 		bcopy(pdu->isp_data,
3359162SPeter.Dunlap@Sun.COM 		    (uint8_t *)(uintptr_t)msg->msg_ds.ds_va +
3369162SPeter.Dunlap@Sun.COM 		    ISER_HEADER_LENGTH + pdu->isp_hdrlen,
3379162SPeter.Dunlap@Sun.COM 		    pdu->isp_datalen);
3389162SPeter.Dunlap@Sun.COM 
3399162SPeter.Dunlap@Sun.COM 		/* Set the SGE's ds_len */
3409162SPeter.Dunlap@Sun.COM 		msg->msg_ds.ds_len = ISER_HEADER_LENGTH + pdu->isp_hdrlen +
3419162SPeter.Dunlap@Sun.COM 		    pdu->isp_datalen;
3429162SPeter.Dunlap@Sun.COM 	} else {
3439162SPeter.Dunlap@Sun.COM 		/* No data, so set the SGE's ds_len to the headers length */
3449162SPeter.Dunlap@Sun.COM 		msg->msg_ds.ds_len = ISER_HEADER_LENGTH + pdu->isp_hdrlen;
3459162SPeter.Dunlap@Sun.COM 	}
3469162SPeter.Dunlap@Sun.COM 
3479162SPeter.Dunlap@Sun.COM 	/*
3489162SPeter.Dunlap@Sun.COM 	 * Build Work Request to be posted on the Send Queue.
3499162SPeter.Dunlap@Sun.COM 	 */
3509162SPeter.Dunlap@Sun.COM 	bzero(&wr, sizeof (wr));
3519162SPeter.Dunlap@Sun.COM 
3529162SPeter.Dunlap@Sun.COM 	/* Allocate an iSER WR handle and tuck the msg and pdu into it */
3539162SPeter.Dunlap@Sun.COM 	iser_wr = iser_wr_get();
3549162SPeter.Dunlap@Sun.COM 	if (iser_wr == NULL) {
3559162SPeter.Dunlap@Sun.COM 		ISER_LOG(CE_NOTE, "iser_xfer_ctrlpdu: unable to allocate "
3569162SPeter.Dunlap@Sun.COM 		    "iser wr handle");
3579162SPeter.Dunlap@Sun.COM 		iser_msg_free(msg);
35810101SPriya.Krishnan@Sun.COM 		mutex_exit(&chan->ic_conn->ic_lock);
3599162SPeter.Dunlap@Sun.COM 		return (ISER_STATUS_FAIL);
3609162SPeter.Dunlap@Sun.COM 	}
3619162SPeter.Dunlap@Sun.COM 	iser_wr->iw_pdu = pdu;
3629162SPeter.Dunlap@Sun.COM 	iser_wr->iw_msg = msg;
3639162SPeter.Dunlap@Sun.COM 	iser_wr->iw_type = ISER_WR_SEND;
3649162SPeter.Dunlap@Sun.COM 
3659162SPeter.Dunlap@Sun.COM 	/*
3669162SPeter.Dunlap@Sun.COM 	 * Use the address of our generic iser_wr handle as our WRID
3679162SPeter.Dunlap@Sun.COM 	 * and populate the rest of the work request
3689162SPeter.Dunlap@Sun.COM 	 */
3699162SPeter.Dunlap@Sun.COM 	wr.wr_id	= (ibt_wrid_t)(uintptr_t)iser_wr;
3709162SPeter.Dunlap@Sun.COM 	wr.wr_trans	= IBT_RC_SRV;
3719162SPeter.Dunlap@Sun.COM 	wr.wr_opcode	= IBT_WRC_SEND;
3729162SPeter.Dunlap@Sun.COM 	wr.wr_nds	= 1;
3739162SPeter.Dunlap@Sun.COM 	wr.wr_sgl	= &msg->msg_ds;
3749162SPeter.Dunlap@Sun.COM 
37510101SPriya.Krishnan@Sun.COM 	/* Increment this channel's SQ posted count */
37610101SPriya.Krishnan@Sun.COM 	mutex_enter(&chan->ic_sq_post_lock);
37710101SPriya.Krishnan@Sun.COM 	chan->ic_sq_post_count++;
37810101SPriya.Krishnan@Sun.COM 	if (chan->ic_sq_post_count > chan->ic_sq_max_post_count)
37910101SPriya.Krishnan@Sun.COM 		chan->ic_sq_max_post_count = chan->ic_sq_post_count;
38010101SPriya.Krishnan@Sun.COM 	mutex_exit(&chan->ic_sq_post_lock);
38110101SPriya.Krishnan@Sun.COM 
3829162SPeter.Dunlap@Sun.COM 	/* Post Send Work Request on the specified channel */
3839162SPeter.Dunlap@Sun.COM 	status = ibt_post_send(chan->ic_chanhdl, &wr, 1, NULL);
3849162SPeter.Dunlap@Sun.COM 	if (status != IBT_SUCCESS) {
3859162SPeter.Dunlap@Sun.COM 		ISER_LOG(CE_NOTE, "iser_xfer_ctrlpdu: ibt_post_send "
3869162SPeter.Dunlap@Sun.COM 		    "failure (%d)", status);
3879162SPeter.Dunlap@Sun.COM 		iser_msg_free(msg);
3889162SPeter.Dunlap@Sun.COM 		iser_wr_free(iser_wr);
38910101SPriya.Krishnan@Sun.COM 		mutex_enter(&chan->ic_sq_post_lock);
39010101SPriya.Krishnan@Sun.COM 		chan->ic_sq_post_count--;
39110101SPriya.Krishnan@Sun.COM 		mutex_exit(&chan->ic_sq_post_lock);
39210101SPriya.Krishnan@Sun.COM 		mutex_exit(&chan->ic_conn->ic_lock);
3939162SPeter.Dunlap@Sun.COM 		return (ISER_STATUS_FAIL);
3949162SPeter.Dunlap@Sun.COM 	}
3959162SPeter.Dunlap@Sun.COM 
39610101SPriya.Krishnan@Sun.COM 	mutex_exit(&chan->ic_conn->ic_lock);
3979162SPeter.Dunlap@Sun.COM 	return (ISER_STATUS_SUCCESS);
3989162SPeter.Dunlap@Sun.COM }
3999162SPeter.Dunlap@Sun.COM 
4009162SPeter.Dunlap@Sun.COM /*
4019162SPeter.Dunlap@Sun.COM  * iser_xfer_buf_to_ini
4029162SPeter.Dunlap@Sun.COM  * This is iSER's implementation of the 'Put_Data' operational primitive.
4039162SPeter.Dunlap@Sun.COM  * The iSCSI layer at the target invokes this function when it is ready to
4049162SPeter.Dunlap@Sun.COM  * return the SCSI Read Data to the initiator. This function generates and
4059162SPeter.Dunlap@Sun.COM  * sends an RDMA Write Message containing the read data to the initiator.
4069162SPeter.Dunlap@Sun.COM  */
4079162SPeter.Dunlap@Sun.COM int
iser_xfer_buf_to_ini(idm_task_t * idt,idm_buf_t * buf)4089162SPeter.Dunlap@Sun.COM iser_xfer_buf_to_ini(idm_task_t *idt, idm_buf_t *buf)
4099162SPeter.Dunlap@Sun.COM {
4109162SPeter.Dunlap@Sun.COM 	iser_conn_t	*iser_conn;
4119162SPeter.Dunlap@Sun.COM 	iser_chan_t	*iser_chan;
4129162SPeter.Dunlap@Sun.COM 	iser_buf_t	*iser_buf;
4139162SPeter.Dunlap@Sun.COM 	iser_wr_t	*iser_wr;
4149162SPeter.Dunlap@Sun.COM 	iser_ctrl_hdr_t	*iser_hdr;
4159162SPeter.Dunlap@Sun.COM 	ibt_send_wr_t	wr;
4169162SPeter.Dunlap@Sun.COM 	uint64_t	reg_raddr;
4179162SPeter.Dunlap@Sun.COM 	uint32_t	reg_rkey;
4189162SPeter.Dunlap@Sun.COM 	int		status;
4199162SPeter.Dunlap@Sun.COM 
4209162SPeter.Dunlap@Sun.COM 	/* Grab the iSER resources from the task and buf handles */
4219162SPeter.Dunlap@Sun.COM 	iser_conn = (iser_conn_t *)idt->idt_ic->ic_transport_private;
4229162SPeter.Dunlap@Sun.COM 	iser_chan = iser_conn->ic_chan;
42310101SPriya.Krishnan@Sun.COM 
42410101SPriya.Krishnan@Sun.COM 	mutex_enter(&iser_chan->ic_conn->ic_lock);
42510101SPriya.Krishnan@Sun.COM 	/* Bail out if the connection is closed */
42610101SPriya.Krishnan@Sun.COM 	if ((iser_chan->ic_conn->ic_stage == ISER_CONN_STAGE_CLOSING) ||
42710101SPriya.Krishnan@Sun.COM 	    (iser_chan->ic_conn->ic_stage == ISER_CONN_STAGE_CLOSED)) {
42810101SPriya.Krishnan@Sun.COM 		mutex_exit(&iser_chan->ic_conn->ic_lock);
42910101SPriya.Krishnan@Sun.COM 		return (ISER_STATUS_FAIL);
43010101SPriya.Krishnan@Sun.COM 	}
43110101SPriya.Krishnan@Sun.COM 
4329162SPeter.Dunlap@Sun.COM 	iser_buf  = (iser_buf_t *)buf->idb_buf_private;
4339162SPeter.Dunlap@Sun.COM 	iser_hdr  = (iser_ctrl_hdr_t *)idt->idt_transport_hdr;
4349162SPeter.Dunlap@Sun.COM 
4359162SPeter.Dunlap@Sun.COM 	/* Pull the Read STag data out of the iSER header in the task hdl */
4369162SPeter.Dunlap@Sun.COM 	reg_raddr = BE_IN64(&iser_hdr->rva);
4379162SPeter.Dunlap@Sun.COM 	reg_rkey  = (ntohl(iser_hdr->rstag));
4389162SPeter.Dunlap@Sun.COM 
4399162SPeter.Dunlap@Sun.COM 	/* Set up the WR raddr and rkey based upon the Read iSER STag */
4409162SPeter.Dunlap@Sun.COM 	bzero(&wr, sizeof (ibt_send_wr_t));
4419162SPeter.Dunlap@Sun.COM 	wr.wr.rc.rcwr.rdma.rdma_raddr = reg_raddr + buf->idb_bufoffset;
4429162SPeter.Dunlap@Sun.COM 	wr.wr.rc.rcwr.rdma.rdma_rkey  = reg_rkey;
4439162SPeter.Dunlap@Sun.COM 
4449162SPeter.Dunlap@Sun.COM 	/* Set the transfer length from the IDM buf handle */
4459162SPeter.Dunlap@Sun.COM 	iser_buf->buf_ds.ds_len	= buf->idb_xfer_len;
4469162SPeter.Dunlap@Sun.COM 
4479162SPeter.Dunlap@Sun.COM 	/* Allocate an iSER WR handle and tuck the IDM buf handle into it */
4489162SPeter.Dunlap@Sun.COM 	iser_wr = iser_wr_get();
4499162SPeter.Dunlap@Sun.COM 	if (iser_wr == NULL) {
4509162SPeter.Dunlap@Sun.COM 		ISER_LOG(CE_NOTE, "iser_xfer_buf_to_ini: unable to allocate "
4519162SPeter.Dunlap@Sun.COM 		    "iser wr handle");
45210101SPriya.Krishnan@Sun.COM 		mutex_exit(&iser_chan->ic_conn->ic_lock);
4539162SPeter.Dunlap@Sun.COM 		return (ISER_STATUS_FAIL);
4549162SPeter.Dunlap@Sun.COM 	}
4559162SPeter.Dunlap@Sun.COM 	iser_wr->iw_buf = buf;
4569162SPeter.Dunlap@Sun.COM 	iser_wr->iw_type = ISER_WR_RDMAW;
4579162SPeter.Dunlap@Sun.COM 
4589162SPeter.Dunlap@Sun.COM 	/* Use the address of our generic iser_wr handle as our WRID */
4599162SPeter.Dunlap@Sun.COM 	wr.wr_id	= (ibt_wrid_t)(uintptr_t)iser_wr;
4609162SPeter.Dunlap@Sun.COM 
4619162SPeter.Dunlap@Sun.COM 	/* Populate the rest of the work request */
4629162SPeter.Dunlap@Sun.COM 	wr.wr_flags	= IBT_WR_SEND_SIGNAL;
4639162SPeter.Dunlap@Sun.COM 	wr.wr_trans	= IBT_RC_SRV;
4649162SPeter.Dunlap@Sun.COM 	wr.wr_opcode	= IBT_WRC_RDMAW;
4659162SPeter.Dunlap@Sun.COM 	wr.wr_nds	= 1;
4669162SPeter.Dunlap@Sun.COM 	wr.wr_sgl	= &iser_buf->buf_ds;
4679162SPeter.Dunlap@Sun.COM 
4689162SPeter.Dunlap@Sun.COM #ifdef DEBUG
4699162SPeter.Dunlap@Sun.COM 	bcopy(&wr, &iser_buf->buf_wr, sizeof (ibt_send_wr_t));
4709162SPeter.Dunlap@Sun.COM #endif
4719162SPeter.Dunlap@Sun.COM 
4729721SPriya.Krishnan@Sun.COM 	DTRACE_ISCSI_8(xfer__start, idm_conn_t *, idt->idt_ic,
4739721SPriya.Krishnan@Sun.COM 	    uintptr_t, buf->idb_buf, uint32_t, buf->idb_bufoffset,
4749721SPriya.Krishnan@Sun.COM 	    uint64_t, reg_raddr, uint32_t, buf->idb_bufoffset,
4759721SPriya.Krishnan@Sun.COM 	    uint32_t,  reg_rkey,
4769721SPriya.Krishnan@Sun.COM 	    uint32_t, buf->idb_xfer_len, int, XFER_BUF_TX_TO_INI);
4779721SPriya.Krishnan@Sun.COM 
4789162SPeter.Dunlap@Sun.COM 	/* Increment this channel's SQ posted count */
4799162SPeter.Dunlap@Sun.COM 	mutex_enter(&iser_chan->ic_sq_post_lock);
4809162SPeter.Dunlap@Sun.COM 	iser_chan->ic_sq_post_count++;
4819162SPeter.Dunlap@Sun.COM 	if (iser_chan->ic_sq_post_count > iser_chan->ic_sq_max_post_count)
4829162SPeter.Dunlap@Sun.COM 		iser_chan->ic_sq_max_post_count = iser_chan->ic_sq_post_count;
4839162SPeter.Dunlap@Sun.COM 	mutex_exit(&iser_chan->ic_sq_post_lock);
4849162SPeter.Dunlap@Sun.COM 
48510101SPriya.Krishnan@Sun.COM 	status = ibt_post_send(iser_chan->ic_chanhdl, &wr, 1, NULL);
48610101SPriya.Krishnan@Sun.COM 	if (status != IBT_SUCCESS) {
48710101SPriya.Krishnan@Sun.COM 		ISER_LOG(CE_NOTE, "iser_xfer_buf_to_ini: ibt_post_send "
48810101SPriya.Krishnan@Sun.COM 		    "failure (%d)", status);
48910101SPriya.Krishnan@Sun.COM 		iser_wr_free(iser_wr);
49010101SPriya.Krishnan@Sun.COM 		mutex_enter(&iser_chan->ic_sq_post_lock);
49110101SPriya.Krishnan@Sun.COM 		iser_chan->ic_sq_post_count--;
49210101SPriya.Krishnan@Sun.COM 		mutex_exit(&iser_chan->ic_sq_post_lock);
49310101SPriya.Krishnan@Sun.COM 		mutex_exit(&iser_chan->ic_conn->ic_lock);
49410101SPriya.Krishnan@Sun.COM 		return (ISER_STATUS_FAIL);
49510101SPriya.Krishnan@Sun.COM 	}
49610101SPriya.Krishnan@Sun.COM 
49710101SPriya.Krishnan@Sun.COM 	mutex_exit(&iser_chan->ic_conn->ic_lock);
4989162SPeter.Dunlap@Sun.COM 	return (ISER_STATUS_SUCCESS);
4999162SPeter.Dunlap@Sun.COM }
5009162SPeter.Dunlap@Sun.COM 
5019162SPeter.Dunlap@Sun.COM /*
5029162SPeter.Dunlap@Sun.COM  * iser_xfer_buf_from_ini
5039162SPeter.Dunlap@Sun.COM  * This is iSER's implementation of the 'Get_Data' operational primitive.
5049162SPeter.Dunlap@Sun.COM  * The iSCSI layer at the target invokes this function when it is ready to
5059162SPeter.Dunlap@Sun.COM  * receive the SCSI Write Data from the initiator. This function generates and
5069162SPeter.Dunlap@Sun.COM  * sends an RDMA Read Message to get the data from the initiator. No R2T PDUs
5079162SPeter.Dunlap@Sun.COM  * are generated.
5089162SPeter.Dunlap@Sun.COM  */
5099162SPeter.Dunlap@Sun.COM int
iser_xfer_buf_from_ini(idm_task_t * idt,idm_buf_t * buf)5109162SPeter.Dunlap@Sun.COM iser_xfer_buf_from_ini(idm_task_t *idt, idm_buf_t *buf)
5119162SPeter.Dunlap@Sun.COM {
5129162SPeter.Dunlap@Sun.COM 	iser_conn_t	*iser_conn;
5139162SPeter.Dunlap@Sun.COM 	iser_chan_t	*iser_chan;
5149162SPeter.Dunlap@Sun.COM 	iser_buf_t	*iser_buf;
5159162SPeter.Dunlap@Sun.COM 	iser_wr_t	*iser_wr;
5169162SPeter.Dunlap@Sun.COM 	iser_ctrl_hdr_t	*iser_hdr;
5179162SPeter.Dunlap@Sun.COM 	ibt_send_wr_t	wr;
5189162SPeter.Dunlap@Sun.COM 	uint64_t	reg_raddr;
5199162SPeter.Dunlap@Sun.COM 	uint32_t	reg_rkey;
5209162SPeter.Dunlap@Sun.COM 	int		status;
5219162SPeter.Dunlap@Sun.COM 
5229162SPeter.Dunlap@Sun.COM 	/* Grab the iSER resources from the task and buf handles */
5239162SPeter.Dunlap@Sun.COM 	iser_conn = (iser_conn_t *)idt->idt_ic->ic_transport_private;
5249162SPeter.Dunlap@Sun.COM 	iser_chan = iser_conn->ic_chan;
52510101SPriya.Krishnan@Sun.COM 
52610101SPriya.Krishnan@Sun.COM 	mutex_enter(&iser_chan->ic_conn->ic_lock);
52710101SPriya.Krishnan@Sun.COM 	/* Bail out if the connection is closed */
52810101SPriya.Krishnan@Sun.COM 	if ((iser_chan->ic_conn->ic_stage == ISER_CONN_STAGE_CLOSING) ||
52910101SPriya.Krishnan@Sun.COM 	    (iser_chan->ic_conn->ic_stage == ISER_CONN_STAGE_CLOSED)) {
53010101SPriya.Krishnan@Sun.COM 		mutex_exit(&iser_chan->ic_conn->ic_lock);
53110101SPriya.Krishnan@Sun.COM 		return (ISER_STATUS_FAIL);
53210101SPriya.Krishnan@Sun.COM 	}
53310101SPriya.Krishnan@Sun.COM 
5349162SPeter.Dunlap@Sun.COM 	iser_buf = (iser_buf_t *)buf->idb_buf_private;
5359162SPeter.Dunlap@Sun.COM 	iser_hdr  = (iser_ctrl_hdr_t *)idt->idt_transport_hdr;
5369162SPeter.Dunlap@Sun.COM 
5379162SPeter.Dunlap@Sun.COM 	/* Pull the Write STag data out of the iSER header in the task hdl */
5389162SPeter.Dunlap@Sun.COM 	reg_raddr = BE_IN64(&iser_hdr->wva);
5399162SPeter.Dunlap@Sun.COM 	reg_rkey  = (ntohl(iser_hdr->wstag));
5409162SPeter.Dunlap@Sun.COM 
5419162SPeter.Dunlap@Sun.COM 	/* Set up the WR raddr and rkey based upon the iSER Write STag */
5429162SPeter.Dunlap@Sun.COM 	bzero(&wr, sizeof (ibt_send_wr_t));
5439162SPeter.Dunlap@Sun.COM 	wr.wr.rc.rcwr.rdma.rdma_raddr = reg_raddr + buf->idb_bufoffset;
5449162SPeter.Dunlap@Sun.COM 	wr.wr.rc.rcwr.rdma.rdma_rkey  = reg_rkey;
5459162SPeter.Dunlap@Sun.COM 
5469162SPeter.Dunlap@Sun.COM 	/* Set the transfer length from the IDM buf handle */
5479162SPeter.Dunlap@Sun.COM 	iser_buf->buf_ds.ds_len	= buf->idb_xfer_len;
5489162SPeter.Dunlap@Sun.COM 
5499162SPeter.Dunlap@Sun.COM 	/* Allocate an iSER WR handle and tuck the IDM buf handle into it */
5509162SPeter.Dunlap@Sun.COM 	iser_wr = iser_wr_get();
5519162SPeter.Dunlap@Sun.COM 	if (iser_wr == NULL) {
5529162SPeter.Dunlap@Sun.COM 		ISER_LOG(CE_NOTE, "iser_xfer_buf_from_ini: unable to allocate "
5539162SPeter.Dunlap@Sun.COM 		    "iser wr handle");
55410101SPriya.Krishnan@Sun.COM 		mutex_exit(&iser_chan->ic_conn->ic_lock);
5559162SPeter.Dunlap@Sun.COM 		return (ISER_STATUS_FAIL);
5569162SPeter.Dunlap@Sun.COM 	}
5579162SPeter.Dunlap@Sun.COM 	iser_wr->iw_buf = buf;
5589162SPeter.Dunlap@Sun.COM 	iser_wr->iw_type = ISER_WR_RDMAR;
5599162SPeter.Dunlap@Sun.COM 
5609162SPeter.Dunlap@Sun.COM 	/* Use the address of our generic iser_wr handle as our WRID */
5619162SPeter.Dunlap@Sun.COM 	wr.wr_id	= (ibt_wrid_t)(uintptr_t)iser_wr;
5629162SPeter.Dunlap@Sun.COM 
5639162SPeter.Dunlap@Sun.COM 	/* Populate the rest of the work request */
5649162SPeter.Dunlap@Sun.COM 	wr.wr_flags	= IBT_WR_SEND_SIGNAL;
5659162SPeter.Dunlap@Sun.COM 	wr.wr_trans	= IBT_RC_SRV;
5669162SPeter.Dunlap@Sun.COM 	wr.wr_opcode	= IBT_WRC_RDMAR;
5679162SPeter.Dunlap@Sun.COM 	wr.wr_nds	= 1;
5689162SPeter.Dunlap@Sun.COM 	wr.wr_sgl	= &iser_buf->buf_ds;
5699162SPeter.Dunlap@Sun.COM 
5709162SPeter.Dunlap@Sun.COM #ifdef DEBUG
5719162SPeter.Dunlap@Sun.COM 	bcopy(&wr, &iser_buf->buf_wr, sizeof (ibt_send_wr_t));
5729162SPeter.Dunlap@Sun.COM #endif
5739162SPeter.Dunlap@Sun.COM 
5749721SPriya.Krishnan@Sun.COM 	DTRACE_ISCSI_8(xfer__start, idm_conn_t *, idt->idt_ic,
5759721SPriya.Krishnan@Sun.COM 	    uintptr_t, buf->idb_buf, uint32_t, buf->idb_bufoffset,
5769721SPriya.Krishnan@Sun.COM 	    uint64_t, reg_raddr, uint32_t, buf->idb_bufoffset,
5779721SPriya.Krishnan@Sun.COM 	    uint32_t,  reg_rkey,
5789721SPriya.Krishnan@Sun.COM 	    uint32_t, buf->idb_xfer_len, int, XFER_BUF_RX_FROM_INI);
5799721SPriya.Krishnan@Sun.COM 
5809162SPeter.Dunlap@Sun.COM 	/* Increment this channel's SQ posted count */
5819162SPeter.Dunlap@Sun.COM 	mutex_enter(&iser_chan->ic_sq_post_lock);
5829162SPeter.Dunlap@Sun.COM 	iser_chan->ic_sq_post_count++;
5839162SPeter.Dunlap@Sun.COM 	if (iser_chan->ic_sq_post_count > iser_chan->ic_sq_max_post_count)
5849162SPeter.Dunlap@Sun.COM 		iser_chan->ic_sq_max_post_count = iser_chan->ic_sq_post_count;
5859162SPeter.Dunlap@Sun.COM 	mutex_exit(&iser_chan->ic_sq_post_lock);
5869162SPeter.Dunlap@Sun.COM 
58710101SPriya.Krishnan@Sun.COM 	status = ibt_post_send(iser_chan->ic_chanhdl, &wr, 1, NULL);
58810101SPriya.Krishnan@Sun.COM 	if (status != IBT_SUCCESS) {
58910101SPriya.Krishnan@Sun.COM 		ISER_LOG(CE_NOTE, "iser_xfer_buf_from_ini: ibt_post_send "
59010101SPriya.Krishnan@Sun.COM 		    "failure (%d)", status);
59110101SPriya.Krishnan@Sun.COM 		iser_wr_free(iser_wr);
59210101SPriya.Krishnan@Sun.COM 		mutex_enter(&iser_chan->ic_sq_post_lock);
59310101SPriya.Krishnan@Sun.COM 		iser_chan->ic_sq_post_count--;
59410101SPriya.Krishnan@Sun.COM 		mutex_exit(&iser_chan->ic_sq_post_lock);
59510101SPriya.Krishnan@Sun.COM 		mutex_exit(&iser_chan->ic_conn->ic_lock);
59610101SPriya.Krishnan@Sun.COM 		return (ISER_STATUS_FAIL);
59710101SPriya.Krishnan@Sun.COM 	}
59810101SPriya.Krishnan@Sun.COM 
59910101SPriya.Krishnan@Sun.COM 	mutex_exit(&iser_chan->ic_conn->ic_lock);
6009162SPeter.Dunlap@Sun.COM 	return (ISER_STATUS_SUCCESS);
6019162SPeter.Dunlap@Sun.COM }
602