ibtl_qp.c revision 5974a6fc6becd7cf6c95fb5bd2cbe9967cf3c93b
/*
* 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 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* These routines implement (most of) the verbs related to
* Queue Pairs.
*/
/* Globals. */
static char ibtf_qp[] = "ibtl";
/* This table indirectly initializes the ibt_cep_next_state[] table. */
typedef struct ibt_cep_next_state_s {
struct {
} ibt_cep_next_state_inits[] = {
};
/* The following data and functions can increase system stability. */
int ibtl_qp_calls_curr;
void
{
while (ibtl_qp_calls_curr >= ibtl_qp_calls_max) {
}
}
void
{
}
/*
* Function:
* ibt_alloc_qp
* Input:
* hca_hdl HCA Handle.
* type Specifies the type of QP to alloc in ibt_alloc_qp()
* qp_attrp Specifies the ibt_qp_alloc_attr_t that are needed to
* allocate a QP and transition it to the RTS state for
* UDs and INIT state for all other QPs.
* Output:
* queue_sizes_p Returned sizes for SQ, RQ, SQ WR SGL elements & RQ
* WR SGL elements.
* qpn_p Returned QP Number of the allocated QP.
* ibt_qp_p The ibt_qp_hdl_t of the allocated QP.
* Returns:
* IBT_SUCCESS
* Description:
* Allocate a QP with specified attributes.
*/
{
switch (type) {
case IBT_UD_RQP:
break;
case IBT_RC_RQP:
break;
case IBT_UC_RQP:
"Transport Type is not supported.");
return (IBT_NOT_SUPPORTED);
case IBT_RD_RQP:
"Transport Type is not supported.");
return (IBT_NOT_SUPPORTED);
default:
/* shouldn't happen ILLEGAL Type */
"%d", type);
return (IBT_QP_SRV_TYPE_INVALID);
}
/* Get CI CQ handles */
return (IBT_CQ_HDL_INVALID);
}
else
/* Allocate Channel structure */
if (retval != IBT_SUCCESS) {
"Failed to allocate QP: %d", retval);
return (retval);
}
/* Initialize the internal QP struct. */
return (retval);
}
/*
* Function:
* ibt_initialize_qp
* Input:
* ibt_qp The previously allocated IBT QP Handle.
* modify_attrp Specifies the QP Modify attributes that to transition
* the QP to the RTS state for UDs (including special QPs)
* and INIT state for all other QPs.
* Output:
* none.
* Returns:
* IBT_SUCCESS
* Description:
* Transition the QP to the RTS state for UDs (including special QPs)
* and INIT state for all other QPs.
*/
{
/*
* Validate the QP Type from the channel with QP Type from the
* modify attribute struct.
*/
"QP Type mismatch: Chan QP Type<%d>, Modify QP Type<%d>",
return (IBT_QP_SRV_TYPE_INVALID);
}
"QP needs to be in RESET state: Chan QP State<%d>",
return (IBT_CHAN_STATE_INVALID);
}
/*
* Initialize the QP to the RTS state for UDs
* and INIT state for all other QPs.
*/
switch (modify_attrp->qp_trans) {
case IBT_UD_SRV:
/*
* Bring the QP to the RTS state.
*/
do {
"modifying qp state to 0x%x", state);
if (status == IBT_SUCCESS) {
}
break;
case IBT_UC_SRV:
case IBT_RD_SRV:
case IBT_RC_SRV:
/*
* Bring the QP to the INIT state.
*/
if (status == IBT_SUCCESS)
break;
default:
/* shouldn't happen ILLEGAL Type */
return (IBT_QP_SRV_TYPE_INVALID);
} /* End switch */
return (status);
}
/*
* Function:
* ibt_alloc_special_qp
* Input:
* hca_hdl HCA Handle.
* type Specifies the type of Special QP to be allocated.
* qp_attrp Specifies the ibt_qp_alloc_attr_t that are needed to
* allocate a special QP.
* Output:
* queue_sizes_p Returned sizes for SQ, RQ, SQ WR SGL elements & RQ
* WR SGL elements.
* qpn_p Returned qpn of the allocated QP.
* ibt_qp_p The ibt_qp_hdl_t of the allocated QP.
* Returns:
* IBT_SUCCESS
* Description:
* Allocate a special QP with specified attributes.
*/
{
switch (type) {
case IBT_SMI_SQP:
case IBT_GSI_SQP:
break;
case IBT_RAWIP_SQP:
"Transport Type is not supported.");
return (IBT_NOT_SUPPORTED);
case IBT_RAWETHER_SQP:
"Transport Type is not supported.");
return (IBT_NOT_SUPPORTED);
default:
/* Shouldn't happen */
"Illegal Type 0x%x", type);
return (IBT_QP_SPECIAL_TYPE_INVALID);
}
/* convert the CQ handles for the CI */
/* Allocate Channel structure */
if (retval != IBT_SUCCESS) {
"Failed to allocate Special QP: %d", retval);
return (retval);
}
/* Initialize the internal QP struct. */
return (retval);
}
/*
* Function:
* ibt_flush_qp
* Input:
* ibtl_qp Handle for QP that needs to be flushed.
* Output:
* none.
* Returns:
* IBT_SUCCESS
* IBT_QP_HDL_INVALID
* Description:
* Put the QP into error state to flush out work requests.
*/
{
"called with a connected RC QP", ibt_qp);
return (IBT_CHAN_STATE_INVALID);
}
}
/*
* Set the QP state to error to flush any uncompleted WRs.
*/
if (retval != IBT_SUCCESS) {
}
return (retval);
}
/*
* ibtl_cm_chan_is_open()
*
* Inform IBTL that the connection has been established on this
* channel so that a later call to ibtl_cm_chan_is_closed()
* will be required to free the QPN used by this channel.
*
* chan Channel Handle
*/
void
{
}
/*
* ibtl_cm_is_chan_closing()
*
* Returns 1, if the connection that has been
* started for this channel has moved to TIMEWAIT
* If not, returns 0
*
* chan Channel Handle
*/
int
{
return (1);
}
return (0);
}
/*
* ibtl_cm_is_chan_closed()
*
* Returns 1, if the connection that has been
* started for this channel has completed TIMEWAIT
* If not, returns 0
*
* chan Channel Handle
*/
int
{
return (1);
}
return (0);
}
/*
* ibtl_cm_chan_is_closing()
*
* Inform IBTL that the TIMEWAIT delay for the connection has been
* started for this channel so that the QP can be freed.
*
* chan Channel Handle
*/
void
{
}
/*
* ibtl_cm_chan_is_closed()
*
* Inform IBTL that the TIMEWAIT delay for the connection has been
* reached for this channel so that the QPN can be reused.
*
* chan Channel Handle
*/
void
{
return;
}
IBT_SUCCESS) {
/* effectively, this is kmem_free(chan); */
/* decrement ha_qpn_cnt and check for close in progress */
} else
"ibc_release_qpn failed: status = %d\n", status);
}
/*
* ibtl_cm_chan_is_reused()
*
* Inform IBTL that the channel is going to be re-used
* chan Channel Handle
*/
void
{
/* channel is no longer in closed state, shall be re-used */
}
/*
* Function: ibt_free_qp()
*
* Input: ibt_qp Handle for Channel(QP) that needs to be freed.
*
* Output: NONE.
*
* Returns: IBT_SUCCESS
* IBT_QP_STATE_INVALID
* IBT_QP_HDL_INVALID
*
* Description:
* Free a previously allocated QP.
*/
{
IBTL_RC_QP_CLOSING) == 0) {
"need to call ibt_close_rc_channel");
return (IBT_CHAN_STATE_INVALID);
}
if (status == IBT_SUCCESS) {
ibtl_hca->ha_qpn_cnt++;
"SUCCESS", ibt_qp);
} else
"ibc_free_qp failed: status = %d", status);
return (status);
}
} else
if (status == IBT_SUCCESS) {
/* effectively, this is kmem_free(ibt_qp); */
} else {
"ibc_free_qp failed with error %d", status);
}
return (status);
}
/* helper function for ibt_query_qp */
static void
{
} else {
}
}
/*
* Function: ibt_query_qp
*
* Input: ibt_qp - The IBT QP Handle.
*
* Output: ibt_qp_query_attrp - Points to a ibt_qp_query_attr_t
* that on return contains all the
* attributes of the specified qp.
*
* Returns: IBT_SUCCESS
* IBT_QP_HDL_INVALID
*
* Description:
* Query QP attributes
*
*/
{
if (retval == IBT_SUCCESS) {
/* need to fill in sgid from port and sgid_ix for RC and UC */
case IBT_RC_SRV:
hca_devp);
hca_devp);
break;
case IBT_UC_SRV:
hca_devp);
hca_devp);
break;
}
} else {
}
return (retval);
}
/*
* Function:
* ibt_modify_qp
* Input:
* ibt_qp The IBT QP Handle.
* flags Specifies which attributes in ibt_qp_mod_attr_t
* are to be modified.
* qp_attrp Points to an ibt_qp_mod_attr_t struct that contains all
* the attributes of the specified QP that a client is
* allowed to modify after a QP has been allocated
* Output:
* actual_sz Returned actual queue sizes.
* Returns:
* IBT_SUCCESS
* Description:
* Modify the attributes of an existing QP.
*/
{
if (retval == IBT_SUCCESS) {
}
} else {
if (retval == IBT_CHAN_STATE_INVALID) {
/* That means our cache had invalid QP state value. */
/* Query the channel (QP) */
}
}
return (retval);
}
/*
* Function:
* ibt_migrate_path
* Input:
* rc_chan A previously allocated RC channel handle.
* Output:
* none.
* Returns:
* IBT_SUCCESS on Success else appropriate error.
* Description:
* Force the CI to use the alternate path. The alternate path becomes
* the primary path. A new alternate path should be loaded and enabled.
*/
{
int retries = 1;
"Invalid Channel type: Applicable only to RC Channel");
return (IBT_CHAN_SRV_TYPE_INVALID);
}
/* ch_current_state is fixed by ibt_query_qp */
return (IBT_CHAN_STATE_INVALID);
retries = 0;
} else /* query_qp should never really fail */
return (IBT_CHAN_STATE_INVALID);
}
/* Call modify_qp */
if (retval != IBT_SUCCESS) {
" ibt_modify_qp() returned = %d", retval);
--retries >= 0) {
/*
* That means our cached 'state' was invalid.
* We know ibt_modify_qp() fixed it up, so it
* might be worth retrying.
*/
return (IBT_CHAN_STATE_INVALID);
" retrying after 'state' fixed");
goto retry;
}
}
return (retval);
}
/*
* Function:
* ibt_set_qp_private
* Input:
* ibt_qp The ibt_qp_hdl_t of the allocated QP.
* clnt_private The client private data.
* Output:
* none.
* Returns:
* none.
* Description:
* Set the client private data.
*/
void
{
}
/*
* Function:
* ibt_get_qp_private
* Input:
* ibt_qp The ibt_qp_hdl_t of the allocated QP.
* Output:
* none.
* Returns:
* The client private data.
* Description:
* Get the client private data.
*/
void *
{
return (ibt_qp->ch_clnt_private);
}
/*
* Function:
* ibt_qp_to_hca_guid
* Input:
* ibt_qp The ibt_qp_hdl_t of the allocated QP.
* Output:
* none.
* Returns:
* hca_guid Returned HCA GUID on which the specified QP is
* allocated. Valid if it is non-NULL on return.
* Description:
* A helper function to retrieve HCA GUID for the specified QP.
*/
{
}
/*
* Function:
* ibt_recover_ud_qp
* Input:
* ibt_qp An QP Handle which is in SQError state.
* Output:
* none.
* Returns:
* IBT_SUCCESS
* IBT_QP_SRV_TYPE_INVALID
* IBT_QP_STATE_INVALID.
* Description:
* Recover an UD QP which has transitioned to SQ Error state. The
* ibt_recover_ud_qp() transitions the QP from SQ Error state to
* Ready-To-Send QP state.
*
* If a work request posted to a UD QP's send queue completes with an
* error (see ibt_wc_status_t), the QP gets transitioned to SQ Error state.
* In order to reuse this QP, ibt_recover_ud_qp() can be used to recover
* the QP to a usable (Ready-to-Send) state.
*/
{
}
/*
* Function:
* ibt_recycle_ud
* Input:
* ud_chan The IBT UD QP Handle.
* various attributes
*
* Output:
* none
* Returns:
* IBT_SUCCESS
* IBT_CHAN_SRV_TYPE_INVALID
* IBT_CHAN_STATE_INVALID
*
* Description:
* Revert the UD QP back to a usable state.
*/
{
"chan %p is not a UD channel", ud_chan);
return (IBT_CHAN_SRV_TYPE_INVALID);
}
if (retval != IBT_SUCCESS) {
return (retval);
}
"chan %p is in state %d (not in ERROR state)",
return (IBT_CHAN_STATE_INVALID);
}
/* transition the QP from ERROR to RESET */
NULL);
if (retval != IBT_SUCCESS) {
"ibt_modify_qp(ERROR=>RESET) failed on chan %p: %d",
return (retval);
}
/* transition the QP back to RTS */
if (retval != IBT_SUCCESS) {
/* the man page says the QP should be left in ERROR state */
(void) ibt_flush_qp(ud_chan);
}
return (retval);
}
/*
* Function:
* ibt_pause_sendq
* Input:
* chan The IBT QP Handle.
* modify_flags IBT_CEP_SET_NOTHING or IBT_CEP_SET_SQD_EVENT
*
* Output:
* none.
* Returns:
* IBT_SUCCESS
* IBT_CHAN_HDL_INVALID
* IBT_CHAN_STATE_INVALID
* IBT_INVALID_PARAM
*
* Description:
* Place the send queue of the specified channel into the send queue
* drained (SQD) state.
*
*/
{
/*
* Set the QP state to SQD.
*/
if (retval != IBT_SUCCESS) {
}
return (retval);
}
/*
* Function:
* ibt_unpause_sendq
* Input:
* chan The IBT Channel Handle.
* Output:
* none.
* Returns:
* IBT_SUCCESS
* IBT_CHAN_HDL_INVALID
* IBT_CHAN_STATE_INVALID
* Description:
* Un-pauses the previously paused channel. This call will transition the
* QP from SQD to RTS state.
*/
{
/*
* Set the QP state to RTS.
*/
if (retval != IBT_SUCCESS) {
}
return (retval);
}
/*
* Function:
* ibt_resize_queues
* Input:
* chan A previously allocated channel handle.
* flags QP Flags
* IBT_SEND_Q
* IBT_RECV_Q
* request_sz Requested new sizes.
* Output:
* actual_sz Returned actual sizes.
* Returns:
* IBT_SUCCESS
* Description:
* a previously opened channel.
*/
{
"Flags <0x%X> not set", flags);
return (IBT_INVALID_PARAM);
}
if (flags & IBT_SEND_Q) {
}
if (flags & IBT_RECV_Q) {
}
if (retval != IBT_SUCCESS) {
}
return (retval);
}
/*
* Function:
* ibt_query_queues
* Input:
* chan A previously allocated channel handle.
* Output:
* actual_sz Returned actual sizes.
* Returns:
* IBT_SUCCESS
* Description:
*/
{
/* Perform Query QP and retrieve QP sizes. */
if (retval != IBT_SUCCESS) {
return (retval);
}
return (retval);
}
/*
* Function:
* ibt_modify_rdma
* Input:
* rc_chan A previously allocated channel handle.
*
* modify_flags Bitwise "or" of any of the following:
*
* flags Channel End Point (CEP) Disable Flags (0 => enable).
* IBT_CEP_NO_RDMA_RD Disable incoming RDMA RD's
* IBT_CEP_NO_RDMA_WR Disable incoming RDMA WR's
* IBT_CEP_NO_ATOMIC Disable incoming Atomics.
* Output:
* none.
* Returns:
* IBT_SUCCESS
* IBT_QP_SRV_TYPE_INVALID
* IBT_CHAN_HDL_INVALID
* IBT_CHAN_ATOMICS_NOT_SUPPORTED
* IBT_CHAN_STATE_INVALID
* Description:
* "disable" flag. Can call this function when the channel is in
* INIT, RTS or SQD states. If called in any other state
* IBT_CHAN_STATE_INVALID is returned. When the operation completes the
* channel state is left unchanged.
*/
{
"Invalid Channel type: 0x%X, Applicable only to RC Channel",
return (IBT_QP_SRV_TYPE_INVALID);
}
/*
* Can only call this function when the channel in INIT, RTS or SQD
* states.
*/
return (IBT_CHAN_STATE_INVALID);
}
if (retval != IBT_SUCCESS) {
}
return (retval);
}
/*
* Function:
* ibt_set_rdma_resource
* Input:
* chan A previously allocated RC channel handle.
* modify_flags Bitwise "or" of any of the following:
* IBT_CEP_SET_RDMARA_OUT Initiator depth (rdma_ra_out)
* IBT_CEP_SET_RDMARA_IN Responder Resources
* (rdma_ra_in)
* Output:
* none.
* Returns:
* IBT_SUCCESS
* Description:
* Change the number of resources to be used for incoming and outgoing
* RDMA reads & Atomics. Can only be called on a previously opened
* RC channel. Can only be called on a paused channel, and this will
* un-pause that channel.
*/
{
"Invalid Channel type: 0x%X, Applicable only to RC Channel",
return (IBT_CHAN_SRV_TYPE_INVALID);
}
if (retval != IBT_SUCCESS) {
}
return (retval);
}
/*
* Function:
* ibt_change_port
* Input:
* rc_chan A previously allocated RC channel handle.
* port_num New HCA port.
* Output:
* none.
* Returns:
* IBT_SUCCESS
* Description:
* Change the primary physical port of a channel. (This is done only if
* HCA supports this capability).
*/
{
"Invalid Channel type: 0x%X, Applicable only to RC Channel",
return (IBT_CHAN_SRV_TYPE_INVALID);
}
if (retval != IBT_SUCCESS) {
}
return (retval);
}
void
ibtl_init_cep_states(void)
{
int index;
int ibt_nstate_inits;
ibt_nstate_inits = sizeof (ibt_cep_next_state_inits) /
sizeof (ibt_cep_next_state_inits[0]);
/*
* Initialize CEP next state table, using an indirect lookup table so
* that this code isn't dependent on the ibt_cep_state_t enum values.
*/
}
}