/*
* 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
*/
/*
*/
/*
*
* This file contains Transport API functions related to
* Host Channel Adapter (HCA) Verbs.
*/
/* Prototype declarations. */
/*
* Function:
* ibt_open_hca
* Input:
* ibt_hdl - IBT Client Handle
* hca_guid - HCA's node GUID.
* Output:
* hca_hdl_p - IBT HCA Handle.
* Returns:
* IBT_SUCCESS
* IBT_HCA_IN_USE
* IBT_HCA_INVALID
* Description:
* and returns a unique IBT Client HCA handle. Clients passes this
* handle on its subsequent references to this device. Once opened by a
* client, a specific HCA cannot be opened again until after it is closed.
* The IBT_HCA_IN_USE error is returned if client tries to open multiple
* times. In this case, previously allocated IBT HCA handle is returned to
* the client. Opening the HCA prepares the HCA for use by the client.
*/
{
/*
* Get HCA Device Info Structure, referenced by HCA GUID.
*/
/*
* If we are here, then the requested HCA device is not present.
* Return the status as Invalid HCA GUID.
*/
"HCA Device Not Found: Invalid HCA GUID");
return (IBT_HCA_INVALID);
}
/*
* Check whether open is allowed for this dip
*/
return (IBT_FAILURE);
}
}
}
/*
* If we are here, then the requested HCA device has detached,
* or is in the process of detaching.
*/
"HCA is busy trying to detach");
return (IBT_HCA_BUSY_DETACHING);
}
/*
* Yes, we found a HCA Device registered with IBTF, which matches with
* the requested HCA_GUID.
*
* Check out whether this client has already opened this HCA device,
* if yes return the status as IBT_HCA_IN_USE.
*/
"ibt_open_hca: Already Open");
return (IBT_HCA_BUSY_CLOSING);
}
/* Already Opened. Return back old HCA Handle. */
return (IBT_HCA_IN_USE);
}
}
/* Create a new HCA Info entity. */
/* Update the HCA Info entity */
/* Update the HCA List, to keep track about the clients using it. */
/* Update the client's list to depict that it uses this HCA device. */
/*
* Return back the address of ibtl_hca_t structure as an opaque
* IBT HCA handle for the clients, to be used in future calls.
*/
return (IBT_SUCCESS);
}
"resources not yet freed by client '%s'\n";
cntr, resource_type, \
} \
/*
* Function:
* ibt_close_hca
* Input:
* hca_hdl - The HCA handle as returned during its open.
* Output:
* none
* Returns:
* IBT_SUCCESS
* IBT_HCA_HDL_INVALID
* IBT_HCA_RESOURCES_NOT_FREED
* Description:
* Close a HCA.
*/
{
/*
* Verify the Input HCA Handle, if fake return error as
* invalid HCA Handle.
*/
break;
"Unable to find this on global HCA list");
return (IBT_HCA_HDL_INVALID);
}
/* Make sure resources have been freed. */
error = 0;
if (error) {
return (IBT_HCA_RESOURCES_NOT_FREED);
}
/* we are now committed to closing the HCA */
while (hca_hdl->ha_qpn_cnt > 0)
/*
* Remove this HCA Device entry form Client's current list of HCA
* Device Instances being used by it.
*/
break;
"Unable to find this HCA on client list");
return (IBT_HCA_HDL_INVALID);
}
/* hcapp now points to a link that points to us */
/*
* Remove this Client's entry from this HCA Device's Clients list.
*/
break;
"Unable to find this HCA on the client's HCA list");
return (IBT_HCA_HDL_INVALID);
}
/* hcapp now points to a link that points to us */
/* Free memory for this HCA Handle */
return (IBT_SUCCESS);
}
void
{
if ((--hca_hdl->ha_qpn_cnt == 0) &&
}
}
/*
* Function:
* ibt_get_hca_list
* Input:
* hca_list_p - Address of pointer updated here.
* Output:
* hca_list_p - Points to an array of ib_guid_t's allocated here.
* Returns:
* The actual number of valid ib_guid_t's returned.
* Description:
* If hca_list_p is not NULL then the memory for the array of GUIDs is
* allocated here and should be freed by the caller using
* ibt_free_hca_list(). If hca_list_p is NULL then no memory is allocated
* by ibt_get_hca_list and only the number of HCAs in a system is returned.
*/
{
hca_count++;
}
if (hca_count == 0)
"HCA device not found");
return (hca_count);
}
*hca_list_p = hca_listp;
/* Traverse Global HCA List & retrieve HCA Node GUIDs. */
}
return (hca_count);
}
/*
* Function:
* ibt_free_hca_list
* Input:
* hca_list - The address of an ib_guid_t pointer.
* entries - The number of ib_guid_t entries to be freed.
* Output:
* none.
* Returns:
* none.
* Description:
* The memory allocated in ibt_get_hca_list() is freed in this function.
*/
void
{
}
/*
* ibtl_portinfo_locked() is called when the portinfo cache is being
* updated. If this port's info update is in progress, we return 0
* immediately and have the c
* unless it's already in progress (distinguished by return value).
* When done updating the portinfo, they call ibtl_portinfo_unlock().
*/
static int
{
for (;;) {
if (hca_devp->hd_portinfo_locked_port == 0) {
return (1); /* not busy, so OK to initiate update */
"HCA %p port %d is already locked",
return (0); /* it's now done, so no need to initiate */
} else {
/* need to wait for other port before we try again */
}
}
}
static void
{
if (hca_devp->hd_portinfo_waiters) {
hca_devp->hd_portinfo_waiters = 0;
"waking up waiters for port %d info on HCA %p",
}
}
/*
* Function:
* ibt_get_port_state
* Input:
* hca_devp - The HCA Dev Info pointer.
* port - Port number to query.
* Output:
* sgid_p - Returned sgid[0], NULL implies no return value.
* base_lid_p - Returned base_lid, NULL implies no return value.
* Returns:
* IBT_SUCCESS
* IBT_HCA_PORT_INVALID
* Description:
* Returns HCA port attributes for one of the HCA ports.
*/
static ibt_status_t
{
"invalid port %d, nports = %d", port,
return (IBT_HCA_PORT_INVALID);
}
if (sgid_p)
if (base_lid_p)
"port %d, port_state %d, base_lid %d",
return (IBT_HCA_PORT_NOT_ACTIVE);
}
"port %d, port_state %d, base_lid %d",
return (IBT_SUCCESS);
}
/*
* Function:
* ibt_get_port_state
* Input:
* hca_hdl - The HCA handle.
* port - Port number to query.
* Output:
* sgid_p - Returned sgid[0], NULL implies no return value.
* base_lid_p - Returned base_lid, NULL implies no return value.
* Returns:
* IBT_SUCCESS
* IBT_HCA_PORT_INVALID
* Description:
* Returns HCA port attributes for one of the HCA ports.
*/
{
return (retval);
}
/*
* Function:
* ibt_get_port_state_byguid
* Input:
* hca_guid - The HCA node GUID.
* port - Port number to query.
* Output:
* sgid_p - Returned sgid[0], NULL implies no return value.
* base_lid_p - Returned base_lid, NULL implies no return value.
* Returns:
* IBT_SUCCESS
* IBT_HCA_PORT_INVALID
* IBT_HCA_INVALID
* Description:
* Returns HCA port attributes for one of the HCA ports.
*/
{
else
return (retval);
}
/*
* Function:
* ibt_query_hca_byguid
* Input:
* hca_guid - The HCA node GUID.
* Output:
* hca_attrs - A pointer to a ibt_hca_attr_t allocated by the caller,
* into which the HCA Attributes are copied.
* Returns:
* IBT_SUCCESS
* IBT_INVALID_PARAM
* IBT_HCA_INVALID
* Description:
* Returns the static attributes of the specified HCA.
*/
{
/* Get HCA Dev Info Structure, referenced by HCA GUID. */
/*
* If we are here, then the requested HCA device is not present.
*/
"Device Not Found");
return (IBT_HCA_INVALID);
}
/* Return back the static HCA attributes */
return (IBT_SUCCESS);
}
/*
* Function:
* ibt_query_hca
* Input:
* hca_hdl - The HCA handle.
* Output:
* hca_attrs - A pointer to a ibt_hca_attr_t allocated by the caller,
* into which the HCA Attributes are copied.
* Returns:
* IBT_SUCCESS
*
* Description:
* Returns the static attributes of the specified HCA.
*/
{
/* Return back the static HCA attributes */
sizeof (ibt_hca_attr_t));
return (IBT_SUCCESS);
}
/*
* Function:
* ibt_query_hca_ports
* Input:
* hca_hdl - The HCA handle.
* port - Port number. If "0", then query ALL Ports.
* Output:
* port_info_p - The address of a pointer to a ibt_hca_portinfo_t struct.
* ports_p - The number of hca ports on the specified HCA.
* size_p - Size of the memory allocated by IBTL to get portinfo,
* to be freed by calling ibt_free_portinfo().
* Returns:
* IBT_SUCCESS
* IBT_HCA_HDL_INVALID
* IBT_HCA_INVALID
* Description:
* Returns HCA port attributes for either "one", or "all" of the HCA ports.
*/
{
return (retval);
}
/*
* Function:
* ibt_query_hca_ports_byguid
* Input:
* hca_guid - The HCA node GUID.
* port - Port number. If "0", then query ALL Ports.
* Output:
* port_info_p - The address of a pointer to a ibt_hca_portinfo_t struct.
* ports_p - The number of hca ports on the specified HCA.
* size_p - Size of the memory allocated by IBTL to get portinfo,
* to be freed by calling ibt_free_portinfo().
* Returns:
* IBT_SUCCESS
* IBT_HCA_HDL_INVALID
* IBT_HCA_INVALID
* Description:
* Returns HCA port attributes for either "one", or "all" of the HCA ports.
*/
{
/*
* If we are here, then the requested HCA device is not present.
* Return the status as Invalid HCA GUID.
*/
*port_info_p = NULL;
"HCA Device Not Found. ");
return (IBT_HCA_INVALID);
}
size_p, 0);
return (retval);
}
/*
* Define the above function for CM's use that uses the cached copy.
*/
{
/*
* If we are here, then the requested HCA device is not present.
* Return the status as Invalid HCA GUID.
*/
*port_info_p = NULL;
"HCA Device Not Found. ");
return (IBT_HCA_INVALID);
}
size_p, 1);
return (retval);
}
/*
* ibtl_query_one_port - fill in portinfo for one port.
*/
static ibt_status_t
int use_cache)
{
"invalid port %d", port);
return (IBT_HCA_PORT_INVALID);
}
/* If the PORT_UP event is not supported, we need to query */
if (use_cache == 0)
*ports_p = 1;
/*
* Calculate how much memory we need for one port, and allocate it.
*/
*port_info_p = p1;
/* initialize the p_pkey_tbl & p_sgid_tbl pointers. */
return (IBT_SUCCESS);
}
/*
* ibtl_query_hca_ports - worker routine to get port_info for clients.
*/
static ibt_status_t
int use_cache)
{
/*
* If user has specified the port num, then query only that port,
* else query all ports.
*/
if (port)
/* If the PORT_UP event is not supported, we need to query */
if (use_cache == 0)
for (i = 0; i < nports; i++)
/*
* Calculate how much memory we need for all ports, and allocate it.
*/
*port_info_p = p1;
/* For each port, update the p_pkey_tbl & p_sgid_tbl ptrs. */
for (i = 0; i < nports; i++) {
p2 += pkey_tbl_len;
p2 += sgid_tbl_len;
p1++;
}
return (IBT_SUCCESS);
}
/*
* Search for a Full pkey. Use the pkey at index 0 if not found.
*/
static void
{
"ibtl_set_default_pkey_ix: portinfop %p, "
"FULL PKEY 0x%x found, pkey_ix is %d",
return;
}
}
"ibtl_set_default_pkey_ix: portinfop %p: failed "
"to find a default PKEY in the table, using PKey 0x%x",
p1->p_def_pkey_ix = 0;
}
/*
* ibtl_reinit_hca_portinfo - update the portinfo cache for use by IBTL.
*
* We have the HCA driver fill in a temporary portinfo, then we bcopy
* it into our cache while holding the appropriate lock.
*/
void
{
int i;
/* we got the lock, so we need to do the portinfo update */
/* invalidate fast_gid_cache */
/* update was NOT in progress, so we do it here */
sp1->p_sgid_tbl =
if (status != IBT_SUCCESS) {
"ibtl_reinit_hca_portinfo(%p, %d): "
"ibc_query_hca_ports() failed: status = %d",
} else {
"ibtl_reinit_hca_portinfo(%p, %d): "
} else {
p1->p_base_lid = 0;
"ibtl_reinit_hca_portinfo(%p, %d): "
}
}
/* Set multism bit accordingly. */
multiSM = 0;
if (sn_pfx == 0) {
} else if (sn_pfx !=
multiSM = 1;
"ibtl_reinit_hca_portinfo: "
"MULTI SM, Port1 SnPfx=0x%llX, "
"Port2 SnPfx=0x%llX", sn_pfx,
}
}
p1++;
}
}
}
/*
* ibtl_init_hca_portinfo - fill in the portinfo cache for use by IBTL.
*/
{
/*
* Calculate how much memory we need for all ports, and allocate it.
*/
/* For each port initialize the p_pkey_tbl & p_sgid_tbl ptrs. */
for (i = 0; i < nports; i++) {
p2 += pkey_tbl_len;
p2 += sgid_tbl_len;
p1++;
}
/* re-direct the call to CI's call */
if (retval != IBT_SUCCESS) {
"ibc_query_hca_ports() failed: status = %d",
hca_devp->hd_portinfo_len = 0;
return (retval);
}
multiSM = 0;
for (i = 0; i < nports; i++) {
if (sn_pfx == 0) {
multiSM = 1;
"ibtl_init_hca_portinfo: MULTI SM, "
"Port1 SnPfx=0x%llX, Port2 SnPfx=0x%llX",
}
} else {
p1->p_base_lid = 0;
}
p1++;
}
return (IBT_SUCCESS);
}
/*
* Function:
* ibt_modify_system_image
* Input:
* hca_hdl - The HCA handle.
* sys_guid - The New system image GUID.
* Description:
* Modify specified HCA's system image GUID.
*/
{
/* Get HCA Dev Info Structure, referenced by HCA GUID. */
/* re-direct the call to CI's call */
return (retval);
}
/*
* Function:
* ibt_modify_system_image_byguid
*
* Input:
* hca_guid - The HCA Node GUID.
* sys_guid - The New system image GUID.
* Description:
* Modify specified HCA's system image GUID.
*/
{
/* Get HCA Dev Info Structure, referenced by HCA GUID. */
/*
* If we are here, then the requested HCA device is not present.
*/
return (IBT_HCA_INVALID);
}
/* re-direct the call to CI's call */
return (retval);
}
/*
* Function:
* ibt_modify_port_byguid
* Input:
* hca_guid - The HCA Guid.
* cmds - A pointer to an array of ibt_port_modify_t cmds. The
* pmod_port field specifies the port to modify (all ports if 0)
* and the pmod_flags field specifies which attribute to reset.
* num_cmds - The number of commands in the cmds array.
* Output:
* none.
* Returns:
* IBT_SUCCESS
* IBT_HCA_HDL_INVALID
* IBT_HCA_CNTR_INVALID
* IBT_HCA_CNTR_VAL_INVALID
* Description:
* Reset the specified port, or all ports attribute(s).
*/
{
/* Get HCA Dev Info Structure, referenced by HCA GUID. */
/*
* If we are here, then the requested HCA device is not present.
*/
return (IBT_HCA_INVALID);
}
/* re-direct the call to CI's call */
return (retval);
}
/*
* Function:
* ibt_modify_port
* Input:
* hca_hdl - The HCA handle.
* cmds - A pointer to an array of ibt_port_modify_t cmds. The
* pmod_port field specifies the port to modify (all ports if 0)
* and the pmod_flags field specifies which attribute to reset.
* num_cmds - The number of commands in the cmds array.
* Output:
* none.
* Returns:
* IBT_SUCCESS
* IBT_HCA_HDL_INVALID
* IBT_HCA_CNTR_INVALID
* IBT_HCA_CNTR_VAL_INVALID
* Description:
* Reset the specified port, or all ports attribute(s).
*/
{
/* re-direct the call to CI's call */
return (retval);
}
/*
* Function:
* ibt_free_portinfo
* Input:
* port_info - The address of an array to a ibt_hca_portinfo_t struct.
* size - Memory Size as returned from ibt_query_hca_ports().
* Output:
* none
* Returns:
* none
* Description:
* Frees the memory allocated for a specified ibt_hca_portinfo_t struct.
*/
void
{
} else {
}
}
/*
* Function:
* ibt_get_hcadevinfo
* Input:
* hca_guid - The HCA's node GUID.
* Output:
* none.
* Returns:
* Pointer to HCA Device Info structure whose HCA GUID is requested or NULL
* Description:
* Get a pointer to HCA Device Info Structure for the requested HCA GUID.
* If no matching HCA GUID Device info is found, NULL is returned.
*/
{
/*
* Check whether a HCA device with requested Node GUID is available.
* This is done, by searching the global HCA devinfo list and
* comparing the Node GUID from the device attribute info.
*/
/* Match Found. */
break;
}
}
return (hca_devp);
}
/*
* Function:
* ibtl_pkey2index
* Input:
* hca_devp - The IBTL HCA Device Info.
* port_num - The HCA port number.
* pkey - The input PKey value, whose index we are interested in.
* Output:
* pkey_ix - The PKey index returned for the specified PKey.
* Returns:
* Description:
* Returns the PKey Index for the specified PKey, the device as specified
* by IBT HCA Handle.
*/
static ibt_status_t
{
uint_t i;
if ((pkey == IB_PKEY_INVALID_FULL) ||
(pkey == IB_PKEY_INVALID_LIMITED))
return (IBT_INVALID_PARAM);
return (IBT_HCA_PORT_INVALID);
}
for (i = 0; i < port_infop->p_pkey_tbl_sz; i++) {
*pkey_ix = i;
return (IBT_SUCCESS);
}
}
return (IBT_INVALID_PARAM);
}
/*
* Function:
* ibtl_index2pkey
* Input:
* hca_devp - The IBTL HCA Device Info.
* port_num - The HCA port
* pkey_ix - The input PKey index, whose PKey we are interested in.
* Output:
* pkey - The returned PKey value.
* Returns:
* Description:
* Returns the PKey value for the specified PKey index, the device as
* specified by IBT HCA Handle.
*/
static ibt_status_t
{
return (IBT_HCA_PORT_INVALID);
}
"pkey index %d out of range (0, %d)",
return (IBT_PKEY_IX_ILLEGAL);
}
if ((*pkey == IB_PKEY_INVALID_FULL) ||
(*pkey == IB_PKEY_INVALID_LIMITED))
return (IBT_PKEY_IX_INVALID);
return (IBT_SUCCESS);
}
/*
* Function:
* ibt_pkey2index
* Input:
* hca_hdl - The IBT HCA handle.
* port_num - The HCA port number.
* pkey - The input PKey value, whose index we are interested in.
* Output:
* pkey_ix - The PKey index returned for the specified PKey.
* Returns:
* Description:
* Returns the PKey Index for the specified PKey, the device as specified
* by IBT HCA Handle.
*/
{
return (retval);
}
/*
* Function:
* ibt_pkey2index_byguid
* Input:
* hca_guid - The HCA's node GUID.
* port_num - The HCA port number.
* pkey - The input PKey value, whose index we are interested in.
* Output:
* pkey_ix - The PKey Index returned for the specified PKey.
* Returns:
* Description:
* Returns the PKey Index for the specified PKey, the device as specified
* by HCA GUID Info.
*/
{
"Invalid HCA GUID 0x%llx", hca_guid);
return (IBT_HCA_INVALID);
}
return (retval);
}
/*
* Function:
* ibt_index2pkey
* Input:
* hca_hdl - The IBT HCA handle.
* port_num - The HCA port
* pkey_ix - The input PKey index, whose PKey we are interested in.
* Output:
* pkey - The returned PKey value.
* Returns:
* Description:
* Returns the PKey value for the specified PKey index, the device as
* specified by IBT HCA Handle.
*/
{
return (retval);
}
/*
* Function:
* ibt_index2pkey_byguid
* Input:
* hca_guid - The HCA's node GUID.
* port_num - The HCA port
* pkey_ix - The input PKey index, whose PKey we are interested in.
* Output:
* pkey - The returned PKey value, for the specified index.
* Returns:
* Description:
* Returns the PKey Index for the specified PKey, the device as specified
* by HCA GUID Info.
*/
{
"Invalid HCA GUID 0x%llx", hca_guid);
return (IBT_HCA_INVALID);
}
return (retval);
}
/*
* Function:
* ibt_set_hca_private
* Input:
* hca_hdl The ibt_hca_hdl_t of the opened HCA.
* clnt_private The client private data.
* Output:
* none.
* Returns:
* none
* Description:
* Sets the client private data.
*/
void
{
}
/*
* Function:
* ibt_get_hca_private
* Input:
* hca_hdl The ibt_hca_hdl_t of the opened HCA.
* Output:
* none
* Returns:
* The client private data.
* Description:
* Retrieves the private data from a specified HCA.
*/
void *
{
return (hca_hdl->ha_clnt_private);
}
/*
* Function:
* ibt_hca_handle_to_guid
* Input:
* hca HCA Handle.
* Output:
* none.
* Returns:
* hca_guid Returned HCA GUID on which the specified Channel is
* allocated. Valid if it is non-NULL on return.
* Description:
* A helper function to retrieve HCA GUID for the specified handle.
*/
{
return (IBTL_HCA2HCAGUID(hca));
}
/*
* Function:
* ibt_hca_guid_to_handle
* Input:
* ibt_hdl The handle returned to the client by the IBTF from
* an ibt_attach() call.
* hca_guid HCA GUID
* Output:
* hca_hdl Returned ibt_hca_hdl_t.
* Returns:
* IBT_SUCCESS
* IBT_HCA_INVALID
* Description:
* A helper function to retrieve a hca handle from a HCA GUID.
*/
{
/*
* Get HCA Device Info Structure, referenced by HCA GUID.
*/
/*
* If we are here, then the requested HCA device is not present.
* Return the status as Invalid HCA GUID.
*/
"HCA Device Not Found: Invalid HCA GUID");
return (rval);
}
/*
* Yes, we found a HCA Device registered with IBTF, which matches with
* the requested HCA_GUID.
*/
rval = IBT_SUCCESS;
break;
}
}
return (rval);
}