hermon_qpmod.c revision 9e39c5ba00a55fa05777cc94b148296af305e135
/*
* 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.
*/
/*
* Hermon Queue Pair Modify Routines
*
* This contains all the routines necessary to implement the
* ModifyQP() verb. This includes all the code for legal
* transitions to and from Reset, Init, RTR, RTS, SQD, SQErr,
* and Error.
*/
#ifdef HERMON_NOTNOW
#endif
/*
* hermon_qp_modify()
* Context: Can be called from interrupt or base context.
*/
/* ARGSUSED */
int
{
int status;
/*
* TODO add support for SUSPEND and RESUME
*/
/*
* Lock the QP so that we can modify it atomically. After grabbing
* the lock, get the current QP state. We will use this current QP
* state to determine the legal transitions (and the checks that need
* to be performed.)
* Below is a case for every possible QP state. In each case, we
* check that no flags are set which are not valid for the possible
* transitions from that state. If these tests pass and the
* state transition we are attempting is legal, then we call one
* of the helper functions. Each of these functions does some
* additional setup before posting the firmware command for the
* appropriate state transition.
*/
/*
* Verify that the transport type matches between the serv_type and the
* qp_trans. A caller to IBT must specify the qp_trans field as
* IBT_UD_SRV, IBT_RC_SRV, or IBT_UC_SRV, depending on the QP. We
* check here that the correct value was specified, based on our
* understanding of the QP serv type.
*
* Because callers specify part of a 'union' based on what QP type they
* think they're working with, this ensures that we do not pickup bogus
* data if the caller thought they were working with a different QP
* type.
*/
return (IBT_QP_SRV_TYPE_INVALID);
}
/*
* If this is a transition to RTS (which is valid from RTR, RTS,
* SQError, and SQ Drain) then we should honor the "current QP state"
* specified by the consumer. This means converting the IBTF QP state
* in "info_p->qp_current_state" to an Hermon QP state. Otherwise, we
* assume that we already know the current state (i.e. whatever it was
* last modified to or queried as - in "qp->qp_state").
*/
if (flags & IBT_CEP_SET_RTR_RTS) {
} else if ((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_RTS)) {
/* Convert the current IBTF QP state to an Hermon QP state */
switch (info_p->qp_current_state) {
case IBT_STATE_RTR:
break;
case IBT_STATE_RTS:
break;
case IBT_STATE_SQE:
break;
case IBT_STATE_SQD:
break;
default:
return (IBT_QP_STATE_INVALID);
}
} else {
}
switch (cur_state) {
case HERMON_QP_RESET:
/*
* Check for attempts to modify invalid attributes from the
* "Reset" state
*/
goto qpmod_fail;
}
/*
* Verify state transition is to either "Init", back to
* "Reset", or to "Error".
*/
if ((flags & IBT_CEP_SET_RESET_INIT) &&
(flags & IBT_CEP_SET_STATE) &&
(mod_state != IBT_STATE_INIT)) {
/* Invalid transition - ambiguous flags */
goto qpmod_fail;
} else if ((flags & IBT_CEP_SET_RESET_INIT) ||
((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_INIT))) {
/*
* Attempt to transition from "Reset" to "Init"
*/
if (status != DDI_SUCCESS) {
goto qpmod_fail;
}
} else if ((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_RESET)) {
/*
* Attempt to transition from "Reset" back to "Reset"
* Nothing to do here really... just drop the lock
* and return success. The qp->qp_state should
* already be set to HERMON_QP_RESET.
*
* Note: We return here because we do not want to fall
* through to the hermon_wrid_from_reset_handling()
* routine below (since we are not really moving
* _out_ of the "Reset" state.
*/
return (DDI_SUCCESS);
} else if ((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_ERROR)) {
/*
* Attempt to transition from "Reset" to "Error"
*/
if (status != DDI_SUCCESS) {
goto qpmod_fail;
}
} else {
/* Invalid transition - return error */
goto qpmod_fail;
}
/*
* Do any additional handling necessary here for the transition
* from the "Reset" state (e.g. re-initialize the workQ WRID
* lists). Note: If hermon_wrid_from_reset_handling() fails,
* then we attempt to transition the QP back to the "Reset"
* state. If that fails, then it is an indication of a serious
* problem (either HW or SW). So we print out a warning
* message and return failure.
*/
if (status != DDI_SUCCESS) {
}
goto qpmod_fail;
}
break;
case HERMON_QP_INIT:
/*
* Check for attempts to modify invalid attributes from the
* "Init" state
*/
goto qpmod_fail;
}
/*
* Verify state transition is to either "RTR", back to "Init",
* to "Reset", or to "Error"
*/
if ((flags & IBT_CEP_SET_INIT_RTR) &&
(flags & IBT_CEP_SET_STATE) &&
(mod_state != IBT_STATE_RTR)) {
/* Invalid transition - ambiguous flags */
goto qpmod_fail;
} else if ((flags & IBT_CEP_SET_INIT_RTR) ||
((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_RTR))) {
/*
* Attempt to transition from "Init" to "RTR"
*/
if (status != DDI_SUCCESS) {
goto qpmod_fail;
}
} else if ((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_INIT)) {
/*
* Attempt to transition from "Init" to "Init"
*/
if (status != DDI_SUCCESS) {
goto qpmod_fail;
}
} else if ((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_RESET)) {
/*
* Attempt to transition from "Init" to "Reset"
*/
if (status != DDI_SUCCESS) {
goto qpmod_fail;
}
/*
* Do any additional handling necessary for the
* transition _to_ the "Reset" state (e.g. update the
* workQ WRID lists)
*/
if (status != IBT_SUCCESS) {
goto qpmod_fail;
}
} else if ((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_ERROR)) {
/*
* Attempt to transition from "Init" to "Error"
*/
if (status != DDI_SUCCESS) {
goto qpmod_fail;
}
} else {
/* Invalid transition - return error */
goto qpmod_fail;
}
break;
case HERMON_QP_RTR:
/*
* Check for attempts to modify invalid attributes from the
* "RTR" state
*/
goto qpmod_fail;
}
/*
* Verify state transition is to either "RTS", "Reset",
* or "Error"
*/
if ((flags & IBT_CEP_SET_RTR_RTS) &&
(flags & IBT_CEP_SET_STATE) &&
(mod_state != IBT_STATE_RTS)) {
/* Invalid transition - ambiguous flags */
goto qpmod_fail;
} else if ((flags & IBT_CEP_SET_RTR_RTS) ||
((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_RTS))) {
/*
* Attempt to transition from "RTR" to "RTS"
*/
if (status != DDI_SUCCESS) {
goto qpmod_fail;
}
} else if ((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_RESET)) {
/*
* Attempt to transition from "RTR" to "Reset"
*/
if (status != DDI_SUCCESS) {
goto qpmod_fail;
}
/*
* Do any additional handling necessary for the
* transition _to_ the "Reset" state (e.g. update the
* workQ WRID lists)
*/
if (status != IBT_SUCCESS) {
goto qpmod_fail;
}
} else if ((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_ERROR)) {
/*
* Attempt to transition from "RTR" to "Error"
*/
if (status != DDI_SUCCESS) {
goto qpmod_fail;
}
} else {
/* Invalid transition - return error */
goto qpmod_fail;
}
break;
case HERMON_QP_RTS:
/*
* Check for attempts to modify invalid attributes from the
* "RTS" state
*/
goto qpmod_fail;
}
/*
* Verify state transition is to either "RTS", "SQD", "Reset",
* or "Error"
*/
if ((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_RTS)) {
/*
* Attempt to transition from "RTS" to "RTS"
*/
if (status != DDI_SUCCESS) {
goto qpmod_fail;
}
} else if ((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_SQD)) {
#ifdef HERMON_NOTNOW
/*
* Attempt to transition from "RTS" to "SQD"
*/
if (status != DDI_SUCCESS) {
goto qpmod_fail;
}
#else
/* hack because of the lack of fw support for SQD */
goto qpmod_fail;
#endif
} else if ((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_RESET)) {
/*
* Attempt to transition from "RTS" to "Reset"
*/
if (status != DDI_SUCCESS) {
goto qpmod_fail;
}
/*
* Do any additional handling necessary for the
* transition _to_ the "Reset" state (e.g. update the
* workQ WRID lists)
*/
if (status != IBT_SUCCESS) {
goto qpmod_fail;
}
} else if ((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_ERROR)) {
/*
* Attempt to transition from "RTS" to "Error"
*/
if (status != DDI_SUCCESS) {
goto qpmod_fail;
}
} else {
/* Invalid transition - return error */
goto qpmod_fail;
}
break;
case HERMON_QP_SQERR:
/*
* Check for attempts to modify invalid attributes from the
* "SQErr" state
*/
goto qpmod_fail;
}
/*
* Verify state transition is to either "RTS", "Reset", or
* "Error"
*/
if ((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_RTS)) {
/*
* Attempt to transition from "SQErr" to "RTS"
*/
if (status != DDI_SUCCESS) {
goto qpmod_fail;
}
} else if ((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_RESET)) {
/*
* Attempt to transition from "SQErr" to "Reset"
*/
if (status != DDI_SUCCESS) {
goto qpmod_fail;
}
/*
* Do any additional handling necessary for the
* transition _to_ the "Reset" state (e.g. update the
* workQ WRID lists)
*/
if (status != IBT_SUCCESS) {
goto qpmod_fail;
}
} else if ((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_ERROR)) {
/*
* Attempt to transition from "SQErr" to "Error"
*/
if (status != DDI_SUCCESS) {
goto qpmod_fail;
}
} else {
/* Invalid transition - return error */
goto qpmod_fail;
}
break;
case HERMON_QP_SQD:
/*
* Check for attempts to modify invalid attributes from the
* "SQD" state
*/
goto qpmod_fail;
}
/*
* Verify state transition is to either "SQD", "RTS", "Reset",
* or "Error"
*/
if ((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_SQD)) {
/*
* Attempt to transition from "SQD" to "SQD"
*/
if (status != DDI_SUCCESS) {
goto qpmod_fail;
}
} else if ((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_RTS)) {
/*
* If still draining SQ, then fail transition attempt
* to RTS, even though this is now done is two steps
* (see below) if the consumer has tried this before
* it's drained, let him fail and wait appropriately
*/
if (qp->qp_sqd_still_draining) {
goto qpmod_fail;
}
/*
* done in SQD2RTS can be done in SQD2SQD. So make this
* a 2-step process. First, set any attributes requsted
* w/ SQD2SQD, but no real transition.
*
* First, Attempt to transition from "SQD" to "SQD"
*/
if (status != DDI_SUCCESS) {
goto qpmod_fail;
}
/*
* The, attempt to transition from "SQD" to "RTS", but
* request only the state transition, no attributes
*/
if (status != DDI_SUCCESS) {
goto qpmod_fail;
}
} else if ((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_RESET)) {
/*
* Attempt to transition from "SQD" to "Reset"
*/
if (status != DDI_SUCCESS) {
goto qpmod_fail;
}
/*
* Do any additional handling necessary for the
* transition _to_ the "Reset" state (e.g. update the
* workQ WRID lists)
*/
if (status != IBT_SUCCESS) {
goto qpmod_fail;
}
} else if ((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_ERROR)) {
/*
* Attempt to transition from "SQD" to "Error"
*/
if (status != DDI_SUCCESS) {
goto qpmod_fail;
}
} else {
/* Invalid transition - return error */
goto qpmod_fail;
}
break;
case HERMON_QP_ERR:
/*
* Verify state transition is to either "Reset" or back to
* "Error"
*/
if ((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_RESET)) {
/*
* Attempt to transition from "Error" to "Reset"
*/
if (status != DDI_SUCCESS) {
goto qpmod_fail;
}
/*
* Do any additional handling necessary for the
* transition _to_ the "Reset" state (e.g. update the
* workQ WRID lists)
*/
if (status != IBT_SUCCESS) {
goto qpmod_fail;
}
} else if ((flags & IBT_CEP_SET_STATE) &&
(mod_state == IBT_STATE_ERROR)) {
/*
* Attempt to transition from "Error" back to "Error"
* Nothing to do here really... just drop the lock
* and return success. The qp->qp_state should
* already be set to HERMON_QP_ERR.
*
*/
return (DDI_SUCCESS);
} else {
/* Invalid transition - return error */
goto qpmod_fail;
}
break;
default:
/*
* Invalid QP state. If we got here then it's a warning of
* a probably serious problem. So print a message and return
* failure
*/
goto qpmod_fail;
}
return (DDI_SUCCESS);
return (status);
}
/*
* hermon_qp_reset2init()
* Context: Can be called from interrupt or base context.
*/
static int
{
int status;
/*
* Grab the temporary QPC entry from QP software state
*/
/*
* Fill in the common fields in the QPC
*/
if (qp->qp_is_special) {
} else {
}
/* HERMON: sched_q is now in the address vector(s) */
0, qp->qp_is_special);
0, qp->qp_is_special);
/* dbr is now an address, not an index */
qpc->sq_wqe_counter = 0;
qpc->rq_wqe_counter = 0;
/*
* HERMON:
* qpc->wqe_baseaddr is replaced by LKey from the cMPT, and
* page_offset, mtt_base_addr_h/l, and log2_page_size will
* be used to map the WQE buffer
* NOTE that the cMPT is created implicitly when the QP is
* transitioned from reset to init
*/
0xFF);
} else {
qpc->srq_number = 0;
}
/* 1.2 verbs extensions disabled for now */
/*
* Now fill in the QPC fields which are specific to transport type
*/
/* Set the QKey */
/*
* Set MTU and message max. Hermon checks the QPC
* MTU settings rather than just the port MTU,
* so set it to maximum size.
*/
if (qp->qp_uses_lso)
else
/* Check for valid port number and fill it in */
0, qp->qp_is_special);
} else {
return (IBT_HCA_PORT_INVALID);
}
/* Check for valid PKey index and fill it in */
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
/* Check for valid port number and fill it in */
0, qp->qp_is_special);
} else {
return (IBT_HCA_PORT_INVALID);
}
/* Check for valid PKey index and fill it in */
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
/*
* and Atomic are ignored by default.
*/
/* Check for valid port number and fill it in */
0, qp->qp_is_special);
} else {
return (IBT_HCA_PORT_INVALID);
}
/* Check for valid PKey index and fill it in */
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
} else {
/*
* Invalid QP transport type. If we got here then it's a
* warning of a probably serious problem. So print a message
* and return failure
*/
return (ibc_get_ci_failure(0));
}
/*
* Post the RST2INIT_QP command to the Hermon firmware
*
* We do a HERMON_NOSLEEP here because we are still holding the
* "qp_lock". If we got raised to interrupt level by priority
* inversion, we do not want to block in this routine waiting for
* success.
*/
if (status != HERMON_CMD_SUCCESS) {
if (status == HERMON_CMD_INVALID_STATUS) {
}
return (ibc_get_ci_failure(0));
}
return (DDI_SUCCESS);
}
/*
* hermon_qp_init2init()
* Context: Can be called from interrupt or base context.
*/
static int
{
int status;
/*
* Grab the temporary QPC entry from QP software state
*/
/*
* Since there are no common fields to be filled in for this command,
* we begin with the QPC fields which are specific to transport type.
*/
/*
* If we are attempting to modify the port for this QP, then
* check for valid port number and fill it in. Also set the
* appropriate flag in the "opmask" parameter.
*/
/*
* set port is not supported in init2init - however, in init2rtr it will
* take the entire qpc, including the embedded sched_q in the path
* structure - so, we can just skip setting the opmask for it explicitly
* and allow it to be set later on
*/
if (flags & IBT_CEP_SET_PORT) {
0, qp->qp_is_special);
} else {
return (IBT_HCA_PORT_INVALID);
}
}
/*
* If we are attempting to modify the PKey index for this QP,
* then check for valid PKey index and fill it in. Also set
* the appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_PKEY_IX) {
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
}
/*
* If we are attempting to modify the QKey for this QP, then
* fill it in and set the appropriate flag in the "opmask"
* parameter.
*/
if (flags & IBT_CEP_SET_QKEY) {
}
/*
* If we are attempting to modify the port for this QP, then
* check for valid port number and fill it in. Also set the
* appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_PORT) {
0, qp->qp_is_special);
} else {
return (IBT_HCA_PORT_INVALID);
}
}
/*
* If we are attempting to modify the PKey index for this QP,
* then check for valid PKey index and fill it in. Also set
* the appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_PKEY_IX) {
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
}
/*
* Check if any of the flags indicate a change in the RDMA
* the "opmask" parameter
*/
/*
* If we are attempting to modify the port for this QP, then
* check for valid port number and fill it in. Also set the
* appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_PORT) {
0, qp->qp_is_special);
} else {
return (IBT_HCA_PORT_INVALID);
}
/* port# cannot be set in this transition - defer to init2rtr */
}
/*
* If we are attempting to modify the PKey index for this QP,
* then check for valid PKey index and fill it in. Also set
* the appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_PKEY_IX) {
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
}
/*
* Check if any of the flags indicate a change in the RDMA
* in the "opmask" parameter. Note: RDMA Read and Atomic are
* not valid for UC transport.
*/
if (flags & IBT_CEP_SET_RDMA_W) {
}
} else {
/*
* Invalid QP transport type. If we got here then it's a
* warning of a probably serious problem. So print a message
* and return failure
*/
return (ibc_get_ci_failure(0));
}
/*
* Post the INIT2INIT_QP command to the Hermon firmware
*
* We do a HERMON_NOSLEEP here because we are still holding the
* "qp_lock". If we got raised to interrupt level by priority
* inversion, we do not want to block in this routine waiting for
* success.
*/
if (status != HERMON_CMD_SUCCESS) {
if (status != HERMON_CMD_BAD_QP_STATE) {
if (status == HERMON_CMD_INVALID_STATUS) {
}
return (ibc_get_ci_failure(0));
} else {
return (IBT_QP_STATE_INVALID);
}
}
return (DDI_SUCCESS);
}
/*
* hermon_qp_init2rtr()
* Context: Can be called from interrupt or base context.
*/
static int
{
int status;
/*
* Grab the temporary QPC entry from QP software state
*/
/*
* Since there are few common fields to be filled in for this command,
* we just do the QPC fields that are specific to transport type.
*/
/*
* If this UD QP is also a "special QP" (QP0 or QP1), then
* the MTU is 256 bytes. However, Hermon checks the QPC
* MTU settings rather than just the port MTU, so we will
* set it to maximum size for all UD.
*/
if (qp->qp_uses_lso)
else
/*
* Save away the MTU value. This is used in future sqd2sqd
* transitions, as the MTU must remain the same in future
* changes.
*/
/*
* If we are attempting to modify the PKey index for this QP,
* then check for valid PKey index and fill it in. Also set
* the appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_PKEY_IX) {
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
}
/*
* If we are attempting to modify the QKey for this QP, then
* fill it in and set the appropriate flag in the "opmask"
* parameter.
*/
if (flags & IBT_CEP_SET_QKEY) {
}
/*
* Set the common primary address path fields
*/
if (status != DDI_SUCCESS) {
return (status);
}
} else {
return (IBT_HCA_PORT_INVALID);
}
/*
* The following values are apparently "required" here (as
* they are part of the IBA-defined "Remote Node Address
* Vector"). However, they are also going to be "required"
* later - at RTR2RTS_QP time. Not sure why. But we set
* them here anyway.
*/
/*
* Setup the destination QP, recv PSN, MTU, max msg size,etc.
* Note max message size is defined to be the maximum IB
* allowed message size (which is 2^31 bytes). Also max
* MTU is defined by HCA port properties.
*/
return (IBT_HCA_PORT_MTU_EXCEEDED);
}
/*
* Save away the MTU value. This is used in future sqd2sqd
* transitions, as the MTU must remain the same in future
* changes.
*/
/*
* Though it is a "required" parameter, "min_rnr_nak" is
* optionally specifiable in Hermon. So we force the
* optional flag here.
*/
/*
* Check that the number of specified "incoming RDMA resources"
* is valid. And if it is, then setup the "rra_max
*/
DDI_SUCCESS) {
return (IBT_INVALID_PARAM);
}
/* don't need to set up ra_buff_indx, implicit for hermon */
/*
* If we are attempting to modify the PKey index for this QP,
* then check for valid PKey index and fill it in. Also set
* the appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_PKEY_IX) {
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
}
/*
* Check if any of the flags indicate a change in the RDMA
* the "opmask" parameter
*/
/*
* Check for optional alternate path and fill in the
* appropriate QPC fields if one is specified
*/
if (flags & IBT_CEP_SET_ALT_PATH) {
/* Set the common alternate address path fields */
if (status != DDI_SUCCESS) {
return (status);
}
/*
* Check for valid alternate path port number and fill
* it in
*/
} else {
return (IBT_HCA_PORT_INVALID);
}
/*
* Check for valid alternate path PKey index and fill
* it in
*/
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
}
/*
* Set the common primary address path fields
*/
if (status != DDI_SUCCESS) {
return (status);
}
} else {
return (IBT_HCA_PORT_INVALID);
}
/*
* Setup the destination QP, recv PSN, MTU, max msg size,etc.
* Note max message size is defined to be the maximum IB
* allowed message size (which is 2^31 bytes). Also max
* MTU is defined by HCA port properties.
*/
return (IBT_HCA_PORT_MTU_EXCEEDED);
}
/*
* Save away the MTU value. This is used in future sqd2sqd
* transitions, as the MTU must remain the same in future
* changes.
*/
/*
* If we are attempting to modify the PKey index for this QP,
* then check for valid PKey index and fill it in. Also set
* the appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_PKEY_IX) {
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
}
/*
* Check if any of the flags indicate a change in the RDMA
* in the "opmask" parameter. Note: RDMA Read and Atomic are
* not valid for UC transport.
*/
if (flags & IBT_CEP_SET_RDMA_W) {
}
/*
* Check for optional alternate path and fill in the
* appropriate QPC fields if one is specified
*/
if (flags & IBT_CEP_SET_ALT_PATH) {
/* Set the common alternate address path fields */
if (status != DDI_SUCCESS) {
return (status);
}
/*
* Check for valid alternate path port number and fill
* it in
*/
} else {
return (IBT_HCA_PORT_INVALID);
}
/*
* Check for valid alternate path PKey index and fill
* it in
*/
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
}
} else {
/*
* Invalid QP transport type. If we got here then it's a
* warning of a probably serious problem. So print a message
* and return failure
*/
return (ibc_get_ci_failure(0));
}
/*
* Post the INIT2RTR_QP command to the Hermon firmware
*
* We do a HERMON_NOSLEEP here because we are still holding the
* "qp_lock". If we got raised to interrupt level by priority
* inversion, we do not want to block in this routine waiting for
* success.
*/
if (status != HERMON_CMD_SUCCESS) {
if (status != HERMON_CMD_BAD_QP_STATE) {
if (status == HERMON_CMD_INVALID_STATUS) {
}
return (ibc_get_ci_failure(0));
} else {
return (IBT_QP_STATE_INVALID);
}
}
return (DDI_SUCCESS);
}
/*
* hermon_qp_rtr2rts()
* Context: Can be called from interrupt or base context.
*/
static int
{
int status;
/*
* Grab the temporary QPC entry from QP software state
*/
/*
* Now fill in the QPC fields which are specific to transport type
*/
/* Set the send PSN */
/*
* If we are attempting to modify the QKey for this QP, then
* fill it in and set the appropriate flag in the "opmask"
* parameter.
*/
if (flags & IBT_CEP_SET_QKEY) {
}
/*
* Setup the send PSN, ACK timeout, and retry counts
*/
/* in qpc now, not path */
/*
* Set "ack_req_freq" based on the configuration variable
*/
/*
* Check that the number of specified "outgoing RDMA resources"
* is valid. And if it is, then setup the "sra_max"
* appropriately
*/
DDI_SUCCESS) {
return (IBT_INVALID_PARAM);
}
/*
* Check if any of the flags indicate a change in the RDMA
* the "opmask" parameter
*/
/*
* If we are attempting to modify the path migration state for
* this QP, then check for valid state and fill it in. Also
* set the appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_MIG) {
} else {
return (IBT_QP_APM_STATE_INVALID);
}
}
/*
* If we are attempting to modify the "Minimum RNR NAK" value
* for this QP, then fill it in and set the appropriate flag
* in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_MIN_RNR_NAK) {
}
/*
* Check for optional alternate path and fill in the
* appropriate QPC fields if one is specified
*/
if (flags & IBT_CEP_SET_ALT_PATH) {
/* Set the common alternate address path fields */
if (status != DDI_SUCCESS) {
return (status);
}
/*
* Check for valid alternate path port number and fill
* it in
*/
} else {
return (IBT_HCA_PORT_INVALID);
}
/*
* Check for valid alternate path PKey index and fill
* it in
*/
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
}
/* Set the send PSN */
/*
* Configure the QP to allow (sending of) all types of allowable
* UC traffic (i.e. RDMA Write).
*/
/*
* Check if any of the flags indicate a change in the RDMA
* in the "opmask" parameter. Note: RDMA Read and Atomic are
* not valid for UC transport.
*/
if (flags & IBT_CEP_SET_RDMA_W) {
}
/*
* If we are attempting to modify the path migration state for
* this QP, then check for valid state and fill it in. Also
* set the appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_MIG) {
} else {
return (IBT_QP_APM_STATE_INVALID);
}
}
/*
* Check for optional alternate path and fill in the
* appropriate QPC fields if one is specified
*/
if (flags & IBT_CEP_SET_ALT_PATH) {
/* Set the common alternate address path fields */
if (status != DDI_SUCCESS) {
return (status);
}
/*
* Check for valid alternate path port number and fill
* it in
*/
} else {
return (IBT_HCA_PORT_INVALID);
}
/*
* Check for valid alternate path PKey index and fill
* it in
*/
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
}
} else {
/*
* Invalid QP transport type. If we got here then it's a
* warning of a probably serious problem. So print a message
* and return failure
*/
return (ibc_get_ci_failure(0));
}
/*
* Post the RTR2RTS_QP command to the Hermon firmware
*
* We do a HERMON_NOSLEEP here because we are still holding the
* "qp_lock". If we got raised to interrupt level by priority
* inversion, we do not want to block in this routine waiting for
* success.
*/
if (status != HERMON_CMD_SUCCESS) {
if (status != HERMON_CMD_BAD_QP_STATE) {
if (status == HERMON_CMD_INVALID_STATUS) {
}
return (ibc_get_ci_failure(0));
} else {
return (IBT_QP_STATE_INVALID);
}
}
return (DDI_SUCCESS);
}
/*
* hermon_qp_rts2rts()
* Context: Can be called from interrupt or base context.
*/
static int
{
int status;
/*
* Grab the temporary QPC entry from QP software state
*/
/*
* Since there are no common fields to be filled in for this command,
* we begin with the QPC fields which are specific to transport type.
*/
/*
* If we are attempting to modify the QKey for this QP, then
* fill it in and set the appropriate flag in the "opmask"
* parameter.
*/
if (flags & IBT_CEP_SET_QKEY) {
}
/*
* Check if any of the flags indicate a change in the RDMA
* the "opmask" parameter
*/
/*
* If we are attempting to modify the path migration state for
* this QP, then check for valid state and fill it in. Also
* set the appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_MIG) {
} else {
return (IBT_QP_APM_STATE_INVALID);
}
}
/*
* If we are attempting to modify the "Minimum RNR NAK" value
* for this QP, then fill it in and set the appropriate flag
* in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_MIN_RNR_NAK) {
}
/*
* Check for optional alternate path and fill in the
* appropriate QPC fields if one is specified
*/
if (flags & IBT_CEP_SET_ALT_PATH) {
/* Set the common alternate address path fields */
if (status != DDI_SUCCESS) {
return (status);
}
/*
* Check for valid alternate path port number and fill
* it in
*/
} else {
return (IBT_HCA_PORT_INVALID);
}
/*
* Check for valid alternate path PKey index and fill
* it in
*/
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
}
/*
* Check if any of the flags indicate a change in the RDMA
* in the "opmask" parameter. Note: RDMA Read and Atomic are
* not valid for UC transport.
*/
if (flags & IBT_CEP_SET_RDMA_W) {
}
/*
* If we are attempting to modify the path migration state for
* this QP, then check for valid state and fill it in. Also
* set the appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_MIG) {
} else {
return (IBT_QP_APM_STATE_INVALID);
}
}
/*
* Check for optional alternate path and fill in the
* appropriate QPC fields if one is specified
*/
if (flags & IBT_CEP_SET_ALT_PATH) {
/* Set the common alternate address path fields */
if (status != DDI_SUCCESS) {
return (status);
}
/*
* Check for valid alternate path port number and fill
* it in
*/
} else {
return (IBT_HCA_PORT_INVALID);
}
/*
* Check for valid alternate path PKey index and fill
* it in
*/
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
}
} else {
/*
* Invalid QP transport type. If we got here then it's a
* warning of a probably serious problem. So print a message
* and return failure
*/
return (ibc_get_ci_failure(0));
}
/*
* Post the RTS2RTS_QP command to the Hermon firmware
*
* We do a HERMON_NOSLEEP here because we are still holding the
* "qp_lock". If we got raised to interrupt level by priority
* inversion, we do not want to block in this routine waiting for
* success.
*/
if (status != HERMON_CMD_SUCCESS) {
if (status != HERMON_CMD_BAD_QP_STATE) {
if (status == HERMON_CMD_INVALID_STATUS) {
}
return (ibc_get_ci_failure(0));
} else {
return (IBT_QP_STATE_INVALID);
}
}
return (DDI_SUCCESS);
}
#ifdef HERMON_NOTNOW
/*
* hermon_qp_rts2sqd()
* Context: Can be called from interrupt or base context.
*/
static int
{
int status;
/*
* Set a flag to indicate whether or not the consumer is interested
* in receiving the SQ drained event. Since we are going to always
* request hardware generation of the SQD event, we use the value in
* "qp_forward_sqd_event" to determine whether or not to pass the event
* to the IBTF or to silently consume it.
*/
/*
* Post the RTS2SQD_QP command to the Hermon firmware
*
* We do a HERMON_NOSLEEP here because we are still holding the
* "qp_lock". If we got raised to interrupt level by priority
* inversion, we do not want to block in this routine waiting for
* success.
*/
if (status != HERMON_CMD_SUCCESS) {
if (status != HERMON_CMD_BAD_QP_STATE) {
if (status == HERMON_CMD_INVALID_STATUS) {
}
return (ibc_get_ci_failure(0));
} else {
return (IBT_QP_STATE_INVALID);
}
}
/*
* Mark the current QP state as "SQ Draining". This allows us to
* distinguish between the two underlying states in SQD. (see QueryQP()
* code in hermon_qp.c)
*/
return (DDI_SUCCESS);
}
#endif
/*
* hermon_qp_sqd2rts()
* Context: Can be called from interrupt or base context.
*/
static int
{
int status;
/*
* Grab the temporary QPC entry from QP software state
*/
/*
* Fill in the common fields in the QPC
*/
/*
* Now fill in the QPC fields which are specific to transport type
*/
/*
* If we are attempting to modify the port for this QP, then
* check for valid port number and fill it in. Also set the
* appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_PORT) {
0, qp->qp_is_special);
} else {
return (IBT_HCA_PORT_INVALID);
}
}
/*
* If we are attempting to modify the PKey index for this QP,
* then check for valid PKey index and fill it in. Also set
* the appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_PKEY_IX) {
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
}
/*
* If we are attempting to modify the QKey for this QP, then
* fill it in and set the appropriate flag in the "opmask"
* parameter.
*/
if (flags & IBT_CEP_SET_QKEY) {
}
/*
* Check if any of the flags indicate a change in the RDMA
* the "opmask" parameter
*/
/*
* If we are attempting to modify the path migration state for
* this QP, then check for valid state and fill it in. Also
* set the appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_MIG) {
} else {
return (IBT_QP_APM_STATE_INVALID);
}
}
/*
* Check for optional alternate path and fill in the
* appropriate QPC fields if one is specified
*/
if (flags & IBT_CEP_SET_ALT_PATH) {
/* Set the common alternate address path fields */
if (status != DDI_SUCCESS) {
return (status);
}
/*
* Check for valid alternate path port number and fill
* it in
*/
} else {
return (IBT_HCA_PORT_INVALID);
}
/*
* Check for valid alternate path PKey index and fill
* it in
*/
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
}
/*
* If we are attempting to modify the number of "outgoing
* RDMA resources" for this QP, then check for valid value and
* fill it in. Also set the appropriate flag in the "opmask"
* parameter.
*/
if (flags & IBT_CEP_SET_RDMARA_OUT) {
&sra_max) != DDI_SUCCESS) {
return (IBT_INVALID_PARAM);
}
}
/*
* If we are attempting to modify the number of "incoming
* RDMA resources" for this QP, then check for valid value and
* update the "rra_max" and "ra_buf_index" fields in the QPC to
* point to the pre-allocated RDB resources (in DDR). Also set
* the appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_RDMARA_IN) {
&rra_max) != DDI_SUCCESS) {
return (IBT_INVALID_PARAM);
}
}
/*
* If we are attempting to modify the "Minimum RNR NAK" value
* for this QP, then fill it in and set the appropriate flag
* in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_MIN_RNR_NAK) {
}
/*
* Check if any of the flags indicate a change in the RDMA
* in the "opmask" parameter. Note: RDMA Read and Atomic are
* not valid for UC transport.
*/
if (flags & IBT_CEP_SET_RDMA_W) {
}
/*
* If we are attempting to modify the path migration state for
* this QP, then check for valid state and fill it in. Also
* set the appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_MIG) {
} else {
return (IBT_QP_APM_STATE_INVALID);
}
}
/*
* Check for optional alternate path and fill in the
* appropriate QPC fields if one is specified
*/
if (flags & IBT_CEP_SET_ALT_PATH) {
/* Set the common alternate address path fields */
if (status != DDI_SUCCESS) {
return (status);
}
/*
* Check for valid alternate path port number and fill
* it in
*/
} else {
return (IBT_HCA_PORT_INVALID);
}
/*
* Check for valid alternate path PKey index and fill
* it in
*/
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
}
} else {
/*
* Invalid QP transport type. If we got here then it's a
* warning of a probably serious problem. So print a message
* and return failure
*/
return (ibc_get_ci_failure(0));
}
/*
* Post the SQD2RTS_QP command to the Hermon firmware
*
* We do a HERMON_NOSLEEP here because we are still holding the
* "qp_lock". If we got raised to interrupt level by priority
* inversion, we do not want to block in this routine waiting for
* success.
*/
if (status != HERMON_CMD_SUCCESS) {
if (status != HERMON_CMD_BAD_QP_STATE) {
if (status == HERMON_CMD_INVALID_STATUS) {
}
return (ibc_get_ci_failure(0));
} else {
return (IBT_QP_STATE_INVALID);
}
}
return (DDI_SUCCESS);
}
/*
* hermon_qp_sqd2sqd()
* Context: Can be called from interrupt or base context.
*/
static int
{
int status;
/*
* Grab the temporary QPC entry from QP software state
*/
/*
* Fill in the common fields in the QPC
*/
/*
* Now fill in the QPC fields which are specific to transport type
*/
/*
* If we are attempting to modify the port for this QP, then
* check for valid port number and fill it in. Also set the
* appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_PORT) {
0, qp->qp_is_special);
} else {
return (IBT_HCA_PORT_INVALID);
}
}
/*
* If we are attempting to modify the PKey index for this QP,
* then check for valid PKey index and fill it in. Also set
* the appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_PKEY_IX) {
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
}
/*
* If we are attempting to modify the QKey for this QP, then
* fill it in and set the appropriate flag in the "opmask"
* parameter.
*/
if (flags & IBT_CEP_SET_QKEY) {
}
/*
* Check if any of the flags indicate a change in the RDMA
* the "opmask" parameter
*/
/*
* Check for optional primary path and fill in the
* appropriate QPC fields if one is specified
*/
if (flags & IBT_CEP_SET_ADDS_VECT) {
/* Set the common primary address path fields */
if (status != DDI_SUCCESS) {
return (status);
}
} else {
return (IBT_HCA_PORT_INVALID);
}
/*
* MTU changes as part of sqd2sqd are not allowed.
* Simply keep the same MTU value here, stored in the
* qphdl from init2rtr time.
*/
}
/*
* If we are attempting to modify the path migration state for
* this QP, then check for valid state and fill it in. Also
* set the appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_MIG) {
} else {
return (IBT_QP_APM_STATE_INVALID);
}
}
/*
* If we are attempting to modify the PKey index for this QP,
* then check for valid PKey index and fill it in. Also set
* the appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_PKEY_IX) {
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
}
/*
* If we are attempting to modify the port for this QP, then
* check for valid port number and fill it in. Also set the
* appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_PORT) {
} else {
return (IBT_HCA_PORT_INVALID);
}
}
/*
* Check for optional alternate path and fill in the
* appropriate QPC fields if one is specified
*/
if (flags & IBT_CEP_SET_ALT_PATH) {
/* Set the common alternate address path fields */
if (status != DDI_SUCCESS) {
return (status);
}
/*
* Check for valid alternate path port number and fill
* it in
*/
} else {
return (IBT_HCA_PORT_INVALID);
}
/*
* Check for valid alternate path PKey index and fill
* it in
*/
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
}
/*
* If we are attempting to modify the number of "outgoing
* RDMA resources" for this QP, then check for valid value and
* fill it in. Also set the appropriate flag in the "opmask"
* parameter.
*/
if (flags & IBT_CEP_SET_RDMARA_OUT) {
&sra_max) != DDI_SUCCESS) {
return (IBT_INVALID_PARAM);
}
}
/*
* If we are attempting to modify the number of "incoming
* RDMA resources" for this QP, then check for valid value and
* update the "rra_max" and "ra_buf_index" fields in the QPC to
* point to the pre-allocated RDB resources (in DDR). Also set
* the appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_RDMARA_IN) {
&rra_max) != DDI_SUCCESS) {
return (IBT_INVALID_PARAM);
}
}
/*
* If we are attempting to modify the "Local Ack Timeout" value
* for this QP, then fill it in and set the appropriate flag in
* the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_TIMEOUT) {
}
/*
* If we are attempting to modify the "Retry Count" for this QP,
* then fill it in and set the appropriate flag in the "opmask"
* parameter.
*/
if (flags & IBT_CEP_SET_RETRY) {
}
/*
* If we are attempting to modify the "RNR Retry Count" for this
* QP, then fill it in and set the appropriate flag in the
* "opmask" parameter.
*/
if (flags & IBT_CEP_SET_RNR_NAK_RETRY) {
}
/*
* If we are attempting to modify the "Minimum RNR NAK" value
* for this QP, then fill it in and set the appropriate flag
* in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_MIN_RNR_NAK) {
}
/*
* Check if any of the flags indicate a change in the RDMA
* in the "opmask" parameter. Note: RDMA Read and Atomic are
* not valid for UC transport.
*/
if (flags & IBT_CEP_SET_RDMA_W) {
}
/*
* Check for optional primary path and fill in the
* appropriate QPC fields if one is specified
*/
if (flags & IBT_CEP_SET_ADDS_VECT) {
/* Set the common primary address path fields */
if (status != DDI_SUCCESS) {
return (status);
}
} else {
return (IBT_HCA_PORT_INVALID);
}
/*
* MTU changes as part of sqd2sqd are not allowed.
* Simply keep the same MTU value here, stored in the
* qphdl from init2rtr time.
*/
}
/*
* If we are attempting to modify the path migration state for
* this QP, then check for valid state and fill it in. Also
* set the appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_MIG) {
} else {
return (IBT_QP_APM_STATE_INVALID);
}
}
/*
* If we are attempting to modify the PKey index for this QP,
* then check for valid PKey index and fill it in. Also set
* the appropriate flag in the "opmask" parameter.
*/
if (flags & IBT_CEP_SET_PKEY_IX) {
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
}
/*
* Check for optional alternate path and fill in the
* appropriate QPC fields if one is specified
*/
if (flags & IBT_CEP_SET_ALT_PATH) {
/* Set the common alternate address path fields */
if (status != DDI_SUCCESS) {
return (status);
}
/*
* Check for valid alternate path port number and fill
* it in
*/
} else {
return (IBT_HCA_PORT_INVALID);
}
/*
* Check for valid alternate path PKey index and fill
* it in
*/
} else {
return (IBT_PKEY_IX_ILLEGAL);
}
}
} else {
/*
* Invalid QP transport type. If we got here then it's a
* warning of a probably serious problem. So print a message
* and return failure
*/
return (ibc_get_ci_failure(0));
}
/*
* Post the SQD2SQD_QP command to the Hermon firmware
*
* We do a HERMON_NOSLEEP here because we are still holding the
* "qp_lock". If we got raised to interrupt level by priority
* inversion, we do not want to block in this routine waiting for
* success.
*/
if (status != HERMON_CMD_SUCCESS) {
if (status != HERMON_CMD_BAD_QP_STATE) {
if (status == HERMON_CMD_INVALID_STATUS) {
}
return (ibc_get_ci_failure(0));
} else {
return (IBT_QP_STATE_INVALID);
}
}
return (DDI_SUCCESS);
}
/*
* hermon_qp_sqerr2rts()
* Context: Can be called from interrupt or base context.
*/
static int
{
int status;
/*
* Grab the temporary QPC entry from QP software state
*/
/*
* Since there are no common fields to be filled in for this command,
* we begin with the QPC fields which are specific to transport type.
*/
/*
* If we are attempting to modify the QKey for this QP, then
* fill it in and set the appropriate flag in the "opmask"
* parameter.
*/
if (flags & IBT_CEP_SET_QKEY) {
}
/*
* Check if any of the flags indicate a change in the RDMA
* in the "opmask" parameter. Note: RDMA Read and Atomic are
* not valid for UC transport.
*/
if (flags & IBT_CEP_SET_RDMA_W) {
}
} else {
/*
* Invalid QP transport type. If we got here then it's a
* warning of a probably serious problem. So print a message
* and return failure
*/
return (ibc_get_ci_failure(0));
}
/*
* Post the SQERR2RTS_QP command to the Hermon firmware
*
* We do a HERMON_NOSLEEP here because we are still holding the
* "qp_lock". If we got raised to interrupt level by priority
* inversion, we do not want to block in this routine waiting for
* success.
*/
if (status != HERMON_CMD_SUCCESS) {
if (status != HERMON_CMD_BAD_QP_STATE) {
if (status == HERMON_CMD_INVALID_STATUS) {
}
return (ibc_get_ci_failure(0));
} else {
return (IBT_QP_STATE_INVALID);
}
}
return (DDI_SUCCESS);
}
/*
* hermon_qp_to_error()
* Context: Can be called from interrupt or base context.
*/
static int
{
int status;
/*
* Post the TOERR_QP command to the Hermon firmware
*
* We do a HERMON_NOSLEEP here because we are still holding the
* "qp_lock". If we got raised to interrupt level by priority
* inversion, we do not want to block in this routine waiting for
* success.
*/
if (status != HERMON_CMD_SUCCESS) {
if (status == HERMON_CMD_INVALID_STATUS) {
}
return (ibc_get_ci_failure(0));
}
return (DDI_SUCCESS);
}
/*
* hermon_qp_to_reset()
* Context: Can be called from interrupt or base context.
*/
int
{
int status;
/*
* Grab the temporary QPC entry from QP software state
*/
/*
* Post the TORST_QP command to the Hermon firmware
*
* We do a HERMON_NOSLEEP here because we are still holding the
* "qp_lock". If we got raised to interrupt level by priority
* inversion, we do not want to block in this routine waiting for
* success.
*/
if (status != HERMON_CMD_SUCCESS) {
if (status == HERMON_CMD_INVALID_STATUS) {
}
return (ibc_get_ci_failure(0));
}
return (DDI_SUCCESS);
}
/*
* hermon_qp_reset2err()
* Context: Can be called from interrupt or base context.
*/
static int
{
int status;
/*
* In order to implement the transition from "Reset" directly to the
* "Error" state, it is necessary to first give ownership of the QP
* context to the Hermon hardware. This is accomplished by
* transitioning the QP to "Init" as an intermediate step and then,
* immediately transitioning to "Error".
*
* When this function returns success, the QP context will be owned by
* the Hermon hardware and will be in the "Error" state.
*/
/*
* Grab the temporary QPC entry from QP software state
*/
/*
* Fill in the common fields in the QPC
*/
if (qp->qp_is_special) {
} else {
}
/* dbr is now an address, not an index */
/*
* HERMON:
* qpc->wqe_baseaddr is replaced by LKey from the cMPT, and
* page_offset, mtt_base_addr_h/l, and log2_page_size will
* be used to map the WQE buffer
* NOTE that the cMPT is created implicitly when the QP is
* transitioned from reset to init
*/
qpc->sq_wqe_counter = 0;
qpc->rq_wqe_counter = 0;
} else {
qpc->srq_number = 0;
}
/*
* Now fill in the QPC fields which are specific to transport type
*/
/* Set the UD parameters to an invalid default */
/* Set the RC parameters to invalid default */
/* Set the UC parameters to invalid default */
} else {
/*
* Invalid QP transport type. If we got here then it's a
* warning of a probably serious problem. So print a message
* and return failure
*/
return (ibc_get_ci_failure(0));
}
/*
* Post the RST2INIT_QP command to the Hermon firmware
*
* We do a HERMON_NOSLEEP here because we are still holding the
* "qp_lock". If we got raised to interrupt level by priority
* inversion, we do not want to block in this routine waiting for
* success.
*/
if (status != HERMON_CMD_SUCCESS) {
if (status == HERMON_CMD_INVALID_STATUS) {
}
return (ibc_get_ci_failure(0));
}
/*
* Now post the TOERR_QP command to the Hermon firmware
*
* We still do a HERMON_NOSLEEP here because we are still holding the
* "qp_lock". Note: If this fails (which it really never should),
* it indicates a serious problem in the HW or SW. We try to move
* the QP back to the "Reset" state if possible and print a warning
* message if not. In any case, we return an error here.
*/
if (status != HERMON_CMD_SUCCESS) {
if (status == HERMON_CMD_INVALID_STATUS) {
}
}
return (ibc_get_ci_failure(0));
}
return (DDI_SUCCESS);
}
/*
* hermon_check_rdma_enable_flags()
* Context: Can be called from interrupt or base context.
*/
static uint_t
{
if (flags & IBT_CEP_SET_RDMA_R) {
}
if (flags & IBT_CEP_SET_RDMA_W) {
}
if (flags & IBT_CEP_SET_ATOMIC) {
}
return (opmask);
}
/*
* hermon_qp_validate_resp_rsrc()
* Context: Can be called from interrupt or base context.
*/
static int
{
/*
* Check if number of responder resources is too large. Return an
* error if it is
*/
return (IBT_INVALID_PARAM);
}
/*
* If the number of responder resources is too small, round it up.
* Then find the next highest power-of-2
*/
if (rdma_ra_in == 0) {
rdma_ra_in = 1;
}
} else {
}
return (DDI_SUCCESS);
}
/*
* hermon_qp_validate_init_depth()
* Context: Can be called from interrupt or base context.
*/
static int
{
/*
* Check if requested initiator depth is too large. Return an error
* if it is
*/
return (IBT_INVALID_PARAM);
}
/*
* If the requested initiator depth is too small, round it up.
* Then find the next highest power-of-2
*/
if (rdma_ra_out == 0) {
rdma_ra_out = 1;
}
} else {
}
return (DDI_SUCCESS);
}
/*
* hermon_qp_validate_mtu()
* Context: Can be called from interrupt or base context.
*/
static int
{
/*
* Check for invalid MTU values (i.e. zero or any value larger than
* the HCA's port maximum).
*/
return (IBT_HCA_PORT_MTU_EXCEEDED);
}
return (DDI_SUCCESS);
}