/*
* 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 implements the Directed Route (DR) loopback support in IBMF.
*/
extern int ibmf_trace_level;
/*
* ibmf_i_check_for_loopback():
* Check for DR loopback traffic
*/
int
{
int status;
"ibmf_i_check_for_loopback() enter, msg = 0x%p\n",
/*
* Some HCAs do not handle directed route loopback MADs.
* Such MADs are sent out on the wire instead of being looped back.
* This behavior causes the SM to hang since the SM starts
* its sweep with loopback DR MADs.
* This ibmf workaround does the loopback without passing the MAD
* into the transport layer.
* We should really check a property of the hardware to determine
* whether or not an IB HCA can "hear" itself rather than
* checking for specific HCAs or vendor of HCAs.
*/
} else {
}
blocking);
if (status != IBMF_SUCCESS) {
"ibmf_i_check_for_loopback(): %s\n",
"Failure in DR loopback filter");
"ibmf_i_check_for_loopback() exit\n");
return (status);
}
}
return (IBMF_SUCCESS);
}
/*
* ibmf_i_dr_loopback_term():
* Perform termination processing of a DR loopback transaction
*/
static void
int blocking)
{
"ibmf_i_dr_loopback_term() enter, clientp = 0x%p, msg = 0x%p\n",
if (blocking) {
/*
* For sequenced, and blocking transactions, we wait for
* the response. For non-sequenced, and blocking transactions,
* we are done since the send has completed (no send completion
* as when calling into IBTF).
*/
IBMF_TRANS_STATE_FLAG_SIGNALED) == 0)) {
"ibmf_i_dr_loopback_term(): %s\n",
IBMF_MSG_FLAGS_SEQUENCED) == 0) {
} else {
}
"ibmf_i_dr_loopback_term(): %s\n",
if (msgimplp->im_trans_cb) {
}
} else {
}
}
/*
* ibmf_i_dr_loopback_filter():
* This function intercepts Directed Route MADs with zero hop count,
* or loopback DR MADs. If the MAD is outbound from the SM, the SMA's
* client handle is located, and the receive callback invoked.
* If the MAD is outbound from the SMA, the SM's client handle is located
* and the receive callback invoked.
*
* This filtering is needed for some HCAs where the SMA cannot handle DR
* MAD's that need to be treated as a loopback MAD. On these HCAs, we see
* the zero hopcount MAD being sent out on the wire which it should not.
*/
static int
int blocking)
{
int ret;
"ibmf_i_dr_loopback_filter() enter, clientp = 0x%p, msg = 0x%p\n",
/* set transaction flag for a sequenced transaction */
/*
* If the DR SMP method is a Get or a Set, the target is the SMA, else,
* if the method is a GetResponse, the target is the SM. If the
* Attribute is SMInfo, the target is always the SM.
*/
if (ret != IBMF_SUCCESS) {
"ibmf_i_dr_loopback_filter(): %s\n",
"Client for Mgt Class Subnet Agent not found");
"ibmf_i_dr_loopback_filter() exit\n");
return (ret);
}
if (ret != IBMF_SUCCESS) {
"ibmf_i_dr_loopback_filter(): %s\n",
"Client for Mgt Class Subnet Manager not found")
"ibmf_i_dr_loopback_filter() exit\n");
return (ret);
}
} else {
"ibmf_i_dr_loopback_filter(): %s, method = 0x%x\n",
"ibmf_i_dr_loopback_filter() exit\n");
return (IBMF_FAILURE);
}
/*
* Initialize the Transaction ID and Mgmt Class fields in the
* message context.
* NOTE: The IB MAD header in the incoming MAD is in wire (big-endian)
* format and needs to be converted to the host endian format where
* applicable (multi-byte fields)
*/
/*
* Find the message context in the target client corresponding to the
* transaction ID and management class in the source message context
*/
/*
* If the message has been marked unitialized or done
* release the message mutex and return
*/
if ((rmsgimplp->im_trans_state_flags &
/*
* This thread may notify the client only if the
* transaction is done, the message has been removed
* from the client's message list, and the message
* reference count is 0.
* If the transaction is done, and the message reference
* count = 0, there is still a possibility that a
* packet could arrive for the message and its reference
* count increased if the message is still on the list.
* If the message is still on the list, it will be
* removed by a call to ibmf_i_client_rem_msg() at
* the completion point of the transaction.
* So, the reference count should be checked after the
* message has been removed.
*/
if ((msg_trans_state_flags &
!(msg_flags & IBMF_MSG_FLAGS_ON_LIST) &&
(ref_cnt == 0)) {
}
"ibmf_i_dr_loopback_filter(): %s, msg = 0x%p\n",
"Message already marked for removal, dropping MAD",
"ibmf_i_dr_loopback_filter() exit\n");
return (IBMF_FAILURE);
}
} else {
/* This is an unsolicited message */
sizeof (ibmf_msg_impl_t), KM_NOSLEEP);
"ibmf_i_dr_loopback_filter(): %s\n",
"ibmf_i_dr_loopback_filter() exit\n");
return (IBMF_NO_RESOURCES);
}
/* indicate the client callback is active */
} else {
}
/* Increment the message reference count */
/* add message to client's list; will acquire im_mutex */
/* no one should have touched our state */
/* transition out of uninit state */
}
/* Allocate memory for the receive buffers */
"ibmf_i_dr_loopback_filter(): %s\n",
"ibmf_i_dr_loopback_filter() exit\n");
return (IBMF_NO_RESOURCES);
}
}
/* Copy the send buffers into the receive buffers */
/* Copy the MAD header */
sizeof (ib_mad_hdr_t));
/*
* Copy the management class header
* For DR MADs, class header is of size 40 bytes and start
* right after the MAD header.
*/
sizeof (ib_mad_hdr_t);
/* Copy the management class data */
sizeof (ib_mad_hdr_t) +
/* Copy the global address information from the source message */
(void *)&rmsgimplp->im_global_addr,
sizeof (ibmf_global_addr_info_t));
/* Copy the local address information from the source message */
(void *)&rmsgimplp->im_local_addr,
sizeof (ibmf_addr_info_t));
/*
* destined for.
*/
/*
* Decrement the message reference count
* This count was incremented either when the message was found
* on the client's message list (ibmf_i_find_msg()) or when
* a new message was created for unsolicited data
*/
if (rbuf_alloced) {
}
/* add the source message to the source client's list */
/* remove the destination message from the list */
/*
* Notify the client if the message reference count is zero.
* At this point, we know that the transaction is done and
* the message has been removed from the client's message list.
* So, we only need to make sure the reference count is zero
* before notifying the client.
*/
if (ref_cnt == 0)
/* perform source client transaction termination processing */
return (IBMF_SUCCESS);
}