30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * CDDL HEADER START
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap *
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * The contents of this file are subject to the terms of the
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Common Development and Distribution License (the "License").
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * You may not use this file except in compliance with the License.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap *
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * or http://www.opensolaris.org/os/licensing.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * See the License for the specific language governing permissions
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * and limitations under the License.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap *
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * When distributing Covered Code, include this CDDL HEADER in each
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * If applicable, add the following below this CDDL HEADER, with the
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * fields enclosed by brackets "[]" replaced with your own identifying
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * information: Portions Copyright [yyyy] [name of copyright owner]
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap *
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * CDDL HEADER END
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Use is subject to license terms.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#include <sys/types.h>
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#include <sys/stat.h>
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#include <sys/conf.h>
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#include <sys/ddi.h>
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#include <sys/sunddi.h>
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#include <sys/modctl.h>
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#include <sys/byteorder.h>
a668b114487acbb725f522170849c39f8e844673Priya Krishnan#include <sys/sdt.h>
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#include <sys/ib/clients/iser/iser.h>
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * iser_xfer.c
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapint
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_xfer_hello_msg(iser_chan_t *chan)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_hca_t *hca;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr_t *iser_wr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_msg_t *msg;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ibt_send_wr_t wr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_hello_hdr_t *hdr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap int status;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(chan != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hca = (iser_hca_t *)chan->ic_hca;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (hca == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_xfer_hello_msg: no hca handle found");
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (ISER_STATUS_FAIL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap msg = iser_msg_get(hca, 1, NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (msg == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_xfer_hello_msg: iser message cache "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "alloc failed");
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (ISER_STATUS_FAIL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Send iSER Hello Message to declare iSER parameters to the target */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr = (iser_hello_hdr_t *)(uintptr_t)msg->msg_ds.ds_va;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr->opcode = ISER_OPCODE_HELLO_MSG;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr->rsvd1 = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr->maxver = 1;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr->minver = 1;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr->iser_ird = htons(ISER_IB_DEFAULT_IRD);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr->rsvd2[0] = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr->rsvd2[1] = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Allocate an iSER WR handle and tuck this msg into it */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr = iser_wr_get();
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (iser_wr == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_xfer_hello_msg: unable to allocate "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "iser wr handle");
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_msg_free(msg);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (ISER_STATUS_FAIL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr->iw_msg = msg;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr->iw_type = ISER_WR_SEND;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Use the address of our generic iser_wr handle as our WRID */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_id = (ibt_wrid_t)(uintptr_t)iser_wr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Populate the rest of the work request */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_trans = IBT_RC_SRV;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_opcode = IBT_WRC_SEND;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_nds = 1;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_sgl = &msg->msg_ds;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan /*
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan * Avoid race condition by incrementing this channel's
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan * SQ posted count prior to calling ibt_post_send
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan */
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_enter(&chan->ic_sq_post_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan chan->ic_sq_post_count++;
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan if (chan->ic_sq_post_count > chan->ic_sq_max_post_count)
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan chan->ic_sq_max_post_count = chan->ic_sq_post_count;
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&chan->ic_sq_post_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = ibt_post_send(chan->ic_chanhdl, &wr, 1, NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (status != IBT_SUCCESS) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_xfer_hello_msg: ibt_post_send "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "failure (%d)", status);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_enter(&chan->ic_sq_post_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan chan->ic_sq_post_count--;
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&chan->ic_sq_post_lock);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_msg_free(msg);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr_free(iser_wr);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (ISER_STATUS_FAIL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "Posting iSER Hello message: chan (0x%p): "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "IP [%x to %x]", (void *)chan, chan->ic_localip.un.ip4addr,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap chan->ic_remoteip.un.ip4addr);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (ISER_STATUS_SUCCESS);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapint
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_xfer_helloreply_msg(iser_chan_t *chan)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_hca_t *hca;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr_t *iser_wr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ibt_send_wr_t wr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_msg_t *msg;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_helloreply_hdr_t *hdr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap int status;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(chan != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hca = (iser_hca_t *)chan->ic_hca;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (hca == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_xfer_helloreply_msg: no hca handle "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "found");
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (ISER_STATUS_FAIL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap msg = iser_msg_get(hca, 1, NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (msg == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_xfer_helloreply_msg: iser message "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "cache alloc failed");
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (ISER_STATUS_FAIL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Use the iSER Hello Reply Message */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr = (iser_helloreply_hdr_t *)(uintptr_t)msg->msg_ds.ds_va;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr->opcode = ISER_OPCODE_HELLOREPLY_MSG;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr->rsvd1 = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr->flag = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr->maxver = 1;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr->curver = 1;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr->iser_ord = htons(ISER_IB_DEFAULT_ORD);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr->rsvd2[0] = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr->rsvd2[1] = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Allocate an iSER WR handle and tuck this msg into it */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr = iser_wr_get();
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (iser_wr == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_xfer_helloreply_msg: unable to "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "allocate iser wr handle");
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_msg_free(msg);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (ISER_STATUS_FAIL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr->iw_msg = msg;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr->iw_type = ISER_WR_SEND;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Use the address of our generic iser_wr handle as our WRID */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_id = (ibt_wrid_t)(uintptr_t)iser_wr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Populate the rest of the work request */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_trans = IBT_RC_SRV;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_opcode = IBT_WRC_SEND;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_nds = 1;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_sgl = &msg->msg_ds;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_enter(&chan->ic_sq_post_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan chan->ic_sq_post_count++;
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan if (chan->ic_sq_post_count > chan->ic_sq_max_post_count)
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan chan->ic_sq_max_post_count = chan->ic_sq_post_count;
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&chan->ic_sq_post_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = ibt_post_send(chan->ic_chanhdl, &wr, 1, NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (status != IBT_SUCCESS) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_xfer_helloreply_msg: ibt_post_send "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "failure (%d)", status);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_enter(&chan->ic_sq_post_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan chan->ic_sq_post_count--;
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&chan->ic_sq_post_lock);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_msg_free(msg);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr_free(iser_wr);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (ISER_STATUS_FAIL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "Posting iSER HelloReply message: chan (0x%p): "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "IP [%x to %x]", (void *)chan, chan->ic_localip.un.ip4addr,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap chan->ic_remoteip.un.ip4addr);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (ISER_STATUS_SUCCESS);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * iser_xfer_ctrlpdu
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap *
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * This is iSER's implementation of the 'Send_control' operational primitive.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * This iSER layer uses the Send Message type of RCaP to transfer the iSCSI
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Control-type PDU. A special case is that the transfer of SCSI Data-out PDUs
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * carrying unsolicited data are also treated as iSCSI Control-Type PDUs. The
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * message payload contains an iSER header followed by the iSCSI Control-type
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * the iSCSI Control-type PDU.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * This function is invoked by an initiator iSCSI layer requesting the transfer
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * of a iSCSI command PDU or a target iSCSI layer requesting the transfer of a
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * iSCSI response PDU.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapint
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_xfer_ctrlpdu(iser_chan_t *chan, idm_pdu_t *pdu)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_hca_t *hca;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_ctrl_hdr_t *hdr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_msg_t *msg;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr_t *iser_wr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ibt_send_wr_t wr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap int status;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_mr_t *mr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iscsi_data_hdr_t *bhs;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_conn_t *ic;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_task_t *idt = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_buf_t *buf;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(chan != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_enter(&chan->ic_conn->ic_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan /* Bail out if the connection is closed */
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan if ((chan->ic_conn->ic_stage == ISER_CONN_STAGE_CLOSING) ||
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan (chan->ic_conn->ic_stage == ISER_CONN_STAGE_CLOSED)) {
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&chan->ic_conn->ic_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan return (ISER_STATUS_FAIL);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan }
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan ic = chan->ic_conn->ic_idmc;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan /* Pull the BHS out of the PDU handle */
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan bhs = (iscsi_data_hdr_t *)pdu->isp_hdr;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * All SCSI command PDU (except SCSI Read and SCSI Write) and the SCSI
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Response PDU are sent to the remote end using the SendSE Message.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap *
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan * The StatSN may need to be sent (and possibly advanced) at this time
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan * for some PDUs, identified by the IDM_PDU_SET_STATSN flag.
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan */
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan if (pdu->isp_flags & IDM_PDU_SET_STATSN) {
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan (ic->ic_conn_ops.icb_update_statsn)(NULL, pdu);
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan }
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Setup a Send Message for carrying the iSCSI control-type PDU
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * preceeded by an iSER header.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hca = (iser_hca_t *)chan->ic_hca;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (hca == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_xfer_ctrlpdu: no hca handle found");
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&chan->ic_conn->ic_lock);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (ISER_STATUS_FAIL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap msg = iser_msg_get(hca, 1, NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (msg == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_xfer_ctrlpdu: iser message cache "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "alloc failed");
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&chan->ic_conn->ic_lock);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (ISER_STATUS_FAIL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr = (iser_ctrl_hdr_t *)(uintptr_t)msg->msg_ds.ds_va;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Initialize header assuming no transfers
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bzero(hdr, sizeof (*hdr));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr->opcode = ISER_OPCODE_CTRL_TYPE_PDU;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * On the initiator side, the task buffers will be used to identify
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * if there are any buffers to be advertised
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if ((ic->ic_conn_type == CONN_TYPE_INI) &&
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ((bhs->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_SCSI_CMD) &&
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ((idt = idm_task_find(ic, bhs->itt, bhs->ttt)) != NULL)) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (!list_is_empty(&idt->idt_inbufv)) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap buf = idm_buf_find(&idt->idt_inbufv, 0);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(buf != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mr = (iser_mr_t *)buf->idb_reg_private;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(mr != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr->rsv_flag = 1;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr->rstag = htonl(mr->is_mrrkey);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap BE_OUT64(&hdr->rva, mr->is_mrva);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (!list_is_empty(&idt->idt_outbufv)) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap buf = idm_buf_find(&idt->idt_outbufv, 0);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(buf != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mr = (iser_mr_t *)buf->idb_reg_private;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(mr != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr->wsv_flag = 1;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hdr->wstag = htonl(mr->is_mrrkey);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap BE_OUT64(&hdr->wva, mr->is_mrva);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Release our reference on the task */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_task_rele(idt);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Copy the BHS after the iSER header */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bcopy(pdu->isp_hdr,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (uint8_t *)(uintptr_t)msg->msg_ds.ds_va + ISER_HEADER_LENGTH,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pdu->isp_hdrlen);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (pdu->isp_datalen > 0) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Copy the isp_data after the PDU header */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bcopy(pdu->isp_data,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (uint8_t *)(uintptr_t)msg->msg_ds.ds_va +
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_HEADER_LENGTH + pdu->isp_hdrlen,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pdu->isp_datalen);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Set the SGE's ds_len */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap msg->msg_ds.ds_len = ISER_HEADER_LENGTH + pdu->isp_hdrlen +
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pdu->isp_datalen;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* No data, so set the SGE's ds_len to the headers length */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap msg->msg_ds.ds_len = ISER_HEADER_LENGTH + pdu->isp_hdrlen;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Build Work Request to be posted on the Send Queue.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bzero(&wr, sizeof (wr));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Allocate an iSER WR handle and tuck the msg and pdu into it */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr = iser_wr_get();
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (iser_wr == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_xfer_ctrlpdu: unable to allocate "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "iser wr handle");
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_msg_free(msg);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&chan->ic_conn->ic_lock);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (ISER_STATUS_FAIL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr->iw_pdu = pdu;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr->iw_msg = msg;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr->iw_type = ISER_WR_SEND;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Use the address of our generic iser_wr handle as our WRID
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * and populate the rest of the work request
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_id = (ibt_wrid_t)(uintptr_t)iser_wr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_trans = IBT_RC_SRV;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_opcode = IBT_WRC_SEND;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_nds = 1;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_sgl = &msg->msg_ds;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan /* Increment this channel's SQ posted count */
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_enter(&chan->ic_sq_post_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan chan->ic_sq_post_count++;
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan if (chan->ic_sq_post_count > chan->ic_sq_max_post_count)
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan chan->ic_sq_max_post_count = chan->ic_sq_post_count;
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&chan->ic_sq_post_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Post Send Work Request on the specified channel */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = ibt_post_send(chan->ic_chanhdl, &wr, 1, NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (status != IBT_SUCCESS) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_xfer_ctrlpdu: ibt_post_send "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "failure (%d)", status);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_msg_free(msg);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr_free(iser_wr);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_enter(&chan->ic_sq_post_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan chan->ic_sq_post_count--;
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&chan->ic_sq_post_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&chan->ic_conn->ic_lock);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (ISER_STATUS_FAIL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&chan->ic_conn->ic_lock);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (ISER_STATUS_SUCCESS);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * iser_xfer_buf_to_ini
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * This is iSER's implementation of the 'Put_Data' operational primitive.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * The iSCSI layer at the target invokes this function when it is ready to
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * return the SCSI Read Data to the initiator. This function generates and
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * sends an RDMA Write Message containing the read data to the initiator.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapint
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_xfer_buf_to_ini(idm_task_t *idt, idm_buf_t *buf)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_conn_t *iser_conn;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_chan_t *iser_chan;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_buf_t *iser_buf;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr_t *iser_wr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_ctrl_hdr_t *iser_hdr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ibt_send_wr_t wr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap uint64_t reg_raddr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap uint32_t reg_rkey;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap int status;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Grab the iSER resources from the task and buf handles */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_conn = (iser_conn_t *)idt->idt_ic->ic_transport_private;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_chan = iser_conn->ic_chan;
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_enter(&iser_chan->ic_conn->ic_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan /* Bail out if the connection is closed */
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan if ((iser_chan->ic_conn->ic_stage == ISER_CONN_STAGE_CLOSING) ||
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan (iser_chan->ic_conn->ic_stage == ISER_CONN_STAGE_CLOSED)) {
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&iser_chan->ic_conn->ic_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan return (ISER_STATUS_FAIL);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan }
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_buf = (iser_buf_t *)buf->idb_buf_private;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_hdr = (iser_ctrl_hdr_t *)idt->idt_transport_hdr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Pull the Read STag data out of the iSER header in the task hdl */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap reg_raddr = BE_IN64(&iser_hdr->rva);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap reg_rkey = (ntohl(iser_hdr->rstag));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Set up the WR raddr and rkey based upon the Read iSER STag */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bzero(&wr, sizeof (ibt_send_wr_t));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr.rc.rcwr.rdma.rdma_raddr = reg_raddr + buf->idb_bufoffset;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr.rc.rcwr.rdma.rdma_rkey = reg_rkey;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Set the transfer length from the IDM buf handle */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_buf->buf_ds.ds_len = buf->idb_xfer_len;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Allocate an iSER WR handle and tuck the IDM buf handle into it */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr = iser_wr_get();
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (iser_wr == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_xfer_buf_to_ini: unable to allocate "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "iser wr handle");
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&iser_chan->ic_conn->ic_lock);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (ISER_STATUS_FAIL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr->iw_buf = buf;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr->iw_type = ISER_WR_RDMAW;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Use the address of our generic iser_wr handle as our WRID */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_id = (ibt_wrid_t)(uintptr_t)iser_wr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Populate the rest of the work request */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_flags = IBT_WR_SEND_SIGNAL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_trans = IBT_RC_SRV;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_opcode = IBT_WRC_RDMAW;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_nds = 1;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_sgl = &iser_buf->buf_ds;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#ifdef DEBUG
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bcopy(&wr, &iser_buf->buf_wr, sizeof (ibt_send_wr_t));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#endif
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
a668b114487acbb725f522170849c39f8e844673Priya Krishnan DTRACE_ISCSI_8(xfer__start, idm_conn_t *, idt->idt_ic,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uintptr_t, buf->idb_buf, uint32_t, buf->idb_bufoffset,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint64_t, reg_raddr, uint32_t, buf->idb_bufoffset,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint32_t, reg_rkey,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint32_t, buf->idb_xfer_len, int, XFER_BUF_TX_TO_INI);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan /* Increment this channel's SQ posted count */
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_enter(&iser_chan->ic_sq_post_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan iser_chan->ic_sq_post_count++;
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan if (iser_chan->ic_sq_post_count > iser_chan->ic_sq_max_post_count)
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan iser_chan->ic_sq_max_post_count = iser_chan->ic_sq_post_count;
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&iser_chan->ic_sq_post_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = ibt_post_send(iser_chan->ic_chanhdl, &wr, 1, NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (status != IBT_SUCCESS) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_xfer_buf_to_ini: ibt_post_send "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "failure (%d)", status);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr_free(iser_wr);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_enter(&iser_chan->ic_sq_post_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan iser_chan->ic_sq_post_count--;
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&iser_chan->ic_sq_post_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&iser_chan->ic_conn->ic_lock);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (ISER_STATUS_FAIL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&iser_chan->ic_conn->ic_lock);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (ISER_STATUS_SUCCESS);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * iser_xfer_buf_from_ini
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * This is iSER's implementation of the 'Get_Data' operational primitive.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * The iSCSI layer at the target invokes this function when it is ready to
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * receive the SCSI Write Data from the initiator. This function generates and
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * sends an RDMA Read Message to get the data from the initiator. No R2T PDUs
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * are generated.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapint
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_xfer_buf_from_ini(idm_task_t *idt, idm_buf_t *buf)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_conn_t *iser_conn;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_chan_t *iser_chan;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_buf_t *iser_buf;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr_t *iser_wr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_ctrl_hdr_t *iser_hdr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ibt_send_wr_t wr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap uint64_t reg_raddr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap uint32_t reg_rkey;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap int status;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Grab the iSER resources from the task and buf handles */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_conn = (iser_conn_t *)idt->idt_ic->ic_transport_private;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_chan = iser_conn->ic_chan;
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_enter(&iser_chan->ic_conn->ic_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan /* Bail out if the connection is closed */
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan if ((iser_chan->ic_conn->ic_stage == ISER_CONN_STAGE_CLOSING) ||
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan (iser_chan->ic_conn->ic_stage == ISER_CONN_STAGE_CLOSED)) {
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&iser_chan->ic_conn->ic_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan return (ISER_STATUS_FAIL);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan }
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_buf = (iser_buf_t *)buf->idb_buf_private;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_hdr = (iser_ctrl_hdr_t *)idt->idt_transport_hdr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Pull the Write STag data out of the iSER header in the task hdl */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap reg_raddr = BE_IN64(&iser_hdr->wva);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap reg_rkey = (ntohl(iser_hdr->wstag));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Set up the WR raddr and rkey based upon the iSER Write STag */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bzero(&wr, sizeof (ibt_send_wr_t));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr.rc.rcwr.rdma.rdma_raddr = reg_raddr + buf->idb_bufoffset;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr.rc.rcwr.rdma.rdma_rkey = reg_rkey;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Set the transfer length from the IDM buf handle */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_buf->buf_ds.ds_len = buf->idb_xfer_len;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Allocate an iSER WR handle and tuck the IDM buf handle into it */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr = iser_wr_get();
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (iser_wr == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_xfer_buf_from_ini: unable to allocate "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "iser wr handle");
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&iser_chan->ic_conn->ic_lock);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (ISER_STATUS_FAIL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr->iw_buf = buf;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr->iw_type = ISER_WR_RDMAR;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Use the address of our generic iser_wr handle as our WRID */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_id = (ibt_wrid_t)(uintptr_t)iser_wr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Populate the rest of the work request */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_flags = IBT_WR_SEND_SIGNAL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_trans = IBT_RC_SRV;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_opcode = IBT_WRC_RDMAR;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_nds = 1;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap wr.wr_sgl = &iser_buf->buf_ds;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#ifdef DEBUG
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bcopy(&wr, &iser_buf->buf_wr, sizeof (ibt_send_wr_t));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#endif
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
a668b114487acbb725f522170849c39f8e844673Priya Krishnan DTRACE_ISCSI_8(xfer__start, idm_conn_t *, idt->idt_ic,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uintptr_t, buf->idb_buf, uint32_t, buf->idb_bufoffset,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint64_t, reg_raddr, uint32_t, buf->idb_bufoffset,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint32_t, reg_rkey,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint32_t, buf->idb_xfer_len, int, XFER_BUF_RX_FROM_INI);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan /* Increment this channel's SQ posted count */
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_enter(&iser_chan->ic_sq_post_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan iser_chan->ic_sq_post_count++;
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan if (iser_chan->ic_sq_post_count > iser_chan->ic_sq_max_post_count)
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan iser_chan->ic_sq_max_post_count = iser_chan->ic_sq_post_count;
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&iser_chan->ic_sq_post_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = ibt_post_send(iser_chan->ic_chanhdl, &wr, 1, NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (status != IBT_SUCCESS) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_xfer_buf_from_ini: ibt_post_send "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "failure (%d)", status);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr_free(iser_wr);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_enter(&iser_chan->ic_sq_post_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan iser_chan->ic_sq_post_count--;
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&iser_chan->ic_sq_post_lock);
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&iser_chan->ic_conn->ic_lock);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (ISER_STATUS_FAIL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
a82ec3cf2b07d0f2ebb2e60f41370b7c39a5e71ePriya Krishnan mutex_exit(&iser_chan->ic_conn->ic_lock);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (ISER_STATUS_SUCCESS);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}