/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Routines for completion queue handlers for iSER.
*/
void
{
/*
* Poll for work request completion while successful. If the
* queue empties or otherwise becomes invalid, stop polling.
*/
do {
} while (status == IBT_SUCCESS);
if (status == IBT_CQ_EMPTY) {
/* We've emptied the CQ, rearm it before we're done here */
if (status != IBT_SUCCESS) {
/* Unexpected error */
"ibt_enable_cq_notify error (%d)", status);
return;
}
/* Now, check for more completions after the rearm */
do {
} while (status == IBT_SUCCESS);
}
}
static int
{
int i;
/* Poll ISER_IB_SCQ_POLL_MAX completions from the CQ */
if (status != IBT_SUCCESS) {
if (status != IBT_CQ_EMPTY) {
/* Unexpected error */
"unexpected error (%d)", status);
}
/* CQ is empty. Either way, move along... */
return (status);
}
/*
* Handle each of the completions we've polled
*/
for (i = 0; i < npoll; i++) {
/* Grab the wrid of the completion */
/* Decrement this channel's SQ posted count */
/* Pull in the wr handle */
/* Set an idm_status for return to IDM */
/*
* A non-success status here indicates the QP went
* into an error state while this WR was being
* processed. This can also happen when the
* channel is closed on the remote end. Clean up
* the resources, then push CE_TRANSPORT_FAIL
* into IDM.
*/
/*
* Free the resources attached to this
* completion.
*/
/* Free iser_msg handle */
}
/* Complete the PDU */
}
/* Invoke buffer callback */
mr = ((iser_buf_t *)
#ifdef DEBUG
#endif
int, XFER_BUF_TX_TO_INI);
} else { /* ISER_WR_RDMAR */
int, XFER_BUF_RX_FROM_INI);
}
}
/* Free the iser wr handle */
/*
* Tell IDM that the channel has gone down,
* unless he already knows.
*/
case ISER_CONN_STAGE_IC_FREED:
case ISER_CONN_STAGE_CLOSING:
case ISER_CONN_STAGE_CLOSED:
break;
default:
}
/* Move onto the next completion */
continue;
}
/*
* For a success status, just invoke the PDU or
* buffer completion. We use our WR handle's
* "iw_type" here so that we can properly process
* because the CQE's opcode is invalid if the status
* is failed.
*/
case ISER_WR_SEND:
/* Free the msg handle */
/* This is a hello exchange message */
/*
* We're on the target side,
* and have just successfully
* sent the HelloReply msg.
*/
}
} else {
/* This is a normal control message */
}
/* Free the wr handle */
break;
case ISER_WR_RDMAW:
case ISER_WR_RDMAR:
/*
* Invoke the appropriate callback;
* the buffer will be freed there.
*/
#ifdef DEBUG
sizeof (ibt_wc_t));
#endif
int, XFER_BUF_TX_TO_INI);
} else {
int, XFER_BUF_RX_FROM_INI);
}
/* Free the wr handle */
break;
default:
ASSERT(0);
break;
}
}
return (status);
}
void
{
/*
* Poll for work request completion while successful. If the
* queue empties or otherwise becomes invalid, stop polling.
*/
do {
} while (status == IBT_SUCCESS);
if (status == IBT_CQ_EMPTY) {
/* We've emptied the CQ, rearm it before we're done here */
if (status != IBT_SUCCESS) {
/* Unexpected error */
"ibt_enable_cq_notify error (%d)", status);
return;
}
/* Now, check for more completions after the rearm */
do {
} while (status == IBT_SUCCESS);
}
}
static int
{
int status;
if (status == IBT_CQ_EMPTY) {
/* CQ is empty, return */
return (status);
}
if (status != IBT_SUCCESS) {
/* Unexpected error */
"ibt_poll_cq error (%d)", status);
/* Free the msg handle (if we got it back) */
}
return (status);
}
/* Retrieve the iSER msg handle */
/*
* Decrement the posted level in the RQ, then check
* to see if we need to fill the RQ back up (or if
* we are already on the taskq).
*/
/* Set the pending flag and fire off a post_recv */
if (status != DDI_SUCCESS) {
"task dispatch failed");
/* Failure to launch, unset the pending flag */
}
} else {
}
/*
* Tell IDM that the channel has gone down,
* unless he already knows.
*/
case ISER_CONN_STAGE_IC_FREED:
case ISER_CONN_STAGE_CLOSING:
case ISER_CONN_STAGE_CLOSED:
break;
default:
}
return (DDI_SUCCESS);
} else {
/*
* We have an iSER message in, let's handle it.
* We will free the iser_msg_t later in this path,
* depending upon the action required.
*/
return (DDI_SUCCESS);
}
}
static void
{
int opcode;
int status;
if (opcode == ISER_OPCODE_CTRL_TYPE_PDU) {
/*
* Handle an iSCSI Control PDU iSER message.
* Note we'll free the msg handle in the PDU callback.
*/
if (status != DDI_SUCCESS) {
/*
* We are unable to handle this message, and
* have no way to recover from this. Fail the
* transport.
*/
"iser_iscsihdr_handle");
}
/*
* We are currently not supporting Hello Exchange,
* since OFED iSER does not. May be revisited.
*/
}
"maxver[%d], minver[%d], iser_ird[%d], msg (0x%p)",
/* target is not expected to receive a Hello */
}
/* Prepare and send a HelloReply message */
if (status != ISER_STATUS_SUCCESS) {
}
/* Free this msg handle */
/*
* We are currently not supporting Hello Exchange,
* since OFED iSER does not. May be revisited.
*/
}
"maxver[%d], curver[%d], iser_ord[%d], msg (0x%p)",
/* Free this msg handle */
/*
* Signal the receipt of HelloReply to the waiting thread
* so that the initiator can proceed to the Full Feature
* Phase.
*/
} else {
/* Protocol error: free the msg handle and fail the session */
"terminating session on IDM handle (0x%p)", opcode,
}
}
/* network to host translation for 24b integers */
static uint32_t
{
}
/* ARGSUSED */
static void
{
/* Free the iser msg handle and the PDU handle */
}
int
{
/* Set the iser_msg handle into the transport-private field */
/* Set up a pointer in the pdu handle to the iSER header */
return (ISER_STATUS_FAIL);
}
/*
* Set up a pointer to the iSCSI header, which is directly
* after the iSER header in the message.
*/
if (iscsi_hdrp == NULL) {
return (ISER_STATUS_FAIL);
}
/* Fill in the BHS */
/*
* If datalen > 0, then non-scsi data may be present. Allocate
* space in the PDU handle and set a pointer to the data.
*/
if (pdu->isp_datalen) {
}
/* Process RX PDU */
return (DDI_SUCCESS);
}