#include <sys/ib/mgt/ibmf/ibmf_impl.h>
extern int ibmf_trace_level;
void
ibmf_i_client_add_msg(ibmf_client_t *clientp, ibmf_msg_impl_t *msgimplp)
{
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_client_add_msg_start, IBMF_TNF_TRACE, "",
"ibmf_i_client_add_msg(): clientp = 0x%p, msgp = 0x%p\n",
tnf_opaque, clientp, clientp, tnf_opaque, msg, msgimplp);
ASSERT(MUTEX_NOT_HELD(&msgimplp->im_mutex));
mutex_enter(&clientp->ic_msg_mutex);
mutex_enter(&msgimplp->im_mutex);
if (msgimplp->im_flags & IBMF_MSG_FLAGS_TERMINATION) {
mutex_exit(&msgimplp->im_mutex);
if (clientp->ic_term_msg_list == NULL) {
clientp->ic_term_msg_list = clientp->ic_term_msg_last =
msgimplp;
} else {
msgimplp->im_msg_prev = clientp->ic_term_msg_last;
clientp->ic_term_msg_last->im_msg_next = msgimplp;
clientp->ic_term_msg_last = msgimplp;
}
} else {
mutex_exit(&msgimplp->im_mutex);
clientp->ic_msgs_active++;
mutex_enter(&clientp->ic_kstat_mutex);
IBMF_ADD32_KSTATS(clientp, msgs_active, 1);
mutex_exit(&clientp->ic_kstat_mutex);
if (clientp->ic_msg_list == NULL) {
clientp->ic_msg_list = clientp->ic_msg_last = msgimplp;
} else {
msgimplp->im_msg_prev = clientp->ic_msg_last;
clientp->ic_msg_last->im_msg_next = msgimplp;
clientp->ic_msg_last = msgimplp;
}
}
msgimplp->im_msg_next = NULL;
mutex_enter(&msgimplp->im_mutex);
msgimplp->im_flags |= IBMF_MSG_FLAGS_ON_LIST;
mutex_exit(&msgimplp->im_mutex);
mutex_exit(&clientp->ic_msg_mutex);
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_client_add_msg_end, IBMF_TNF_TRACE, "",
"ibmf_i_client_add_msg() exit\n");
}
void
ibmf_i_client_rem_msg(ibmf_client_t *clientp, ibmf_msg_impl_t *msgimplp,
uint_t *refcnt)
{
ibmf_msg_impl_t *tmpmsg, *prevmsg = NULL;
ASSERT(MUTEX_NOT_HELD(&msgimplp->im_mutex));
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_client_rem_msg_start, IBMF_TNF_TRACE, "",
"ibmf_i_client_rem_msg(): clientp = 0x%p, msgp = 0x%p\n",
tnf_opaque, clientp, clientp, tnf_opaque, msg, msgimplp);
mutex_enter(&clientp->ic_msg_mutex);
mutex_enter(&msgimplp->im_mutex);
if (msgimplp->im_flags & IBMF_MSG_FLAGS_TERMINATION) {
mutex_exit(&msgimplp->im_mutex);
tmpmsg = clientp->ic_term_msg_list;
while (tmpmsg != NULL) {
if (tmpmsg == msgimplp)
break;
prevmsg = tmpmsg;
tmpmsg = tmpmsg->im_msg_next;
}
ASSERT(tmpmsg != NULL);
if (tmpmsg->im_msg_next == NULL)
clientp->ic_term_msg_last = prevmsg;
else
tmpmsg->im_msg_next->im_msg_prev = prevmsg;
if (prevmsg != NULL)
prevmsg->im_msg_next = tmpmsg->im_msg_next;
else
clientp->ic_term_msg_list = tmpmsg->im_msg_next;
} else {
mutex_exit(&msgimplp->im_mutex);
ASSERT(clientp->ic_msgs_active != 0);
clientp->ic_msgs_active--;
mutex_enter(&clientp->ic_kstat_mutex);
IBMF_SUB32_KSTATS(clientp, msgs_active, 1);
mutex_exit(&clientp->ic_kstat_mutex);
tmpmsg = clientp->ic_msg_list;
while (tmpmsg != NULL) {
if (tmpmsg == msgimplp)
break;
prevmsg = tmpmsg;
tmpmsg = tmpmsg->im_msg_next;
}
ASSERT(tmpmsg != NULL);
if (tmpmsg->im_msg_next == NULL)
clientp->ic_msg_last = prevmsg;
else
tmpmsg->im_msg_next->im_msg_prev = prevmsg;
if (prevmsg != NULL)
prevmsg->im_msg_next = tmpmsg->im_msg_next;
else
clientp->ic_msg_list = tmpmsg->im_msg_next;
}
mutex_enter(&msgimplp->im_mutex);
*refcnt = msgimplp->im_ref_count;
msgimplp->im_flags &= ~IBMF_MSG_FLAGS_ON_LIST;
mutex_exit(&msgimplp->im_mutex);
mutex_exit(&clientp->ic_msg_mutex);
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_client_rem_msg_end, IBMF_TNF_TRACE, "",
"ibmf_i_client_rem_msg() exit\n");
}
ibmf_msg_impl_t *
ibmf_i_find_msg(ibmf_client_t *clientp, uint64_t tid, uint8_t mgt_class,
uint8_t r_method, ib_lid_t lid, ib_gid_t *gid, boolean_t gid_pr,
ibmf_rmpp_hdr_t *rmpp_hdr, boolean_t msg_list)
{
ibmf_msg_impl_t *msgimplp;
ib_gid_t *ctx_gidp;
int msg_found;
IBMF_TRACE_5(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_find_msg_start, IBMF_TNF_TRACE, "",
"ibmf_i_find_msg(): clientp = 0x%p, tid = 0x%p, mgmt_class = 0x%x, "
"lid = 0x%x, gidp = 0x%p\n", tnf_opaque, clientp, clientp,
tnf_opaque, tid, tid, tnf_opaque, mgt_class, mgt_class,
tnf_opaque, lid, lid, tnf_opaque, gid, gid);
msg_found = B_FALSE;
mutex_enter(&clientp->ic_msg_mutex);
if (msg_list == IBMF_REG_MSG_LIST)
msgimplp = clientp->ic_msg_list;
else
msgimplp = clientp->ic_term_msg_list;
while (msgimplp != NULL) {
if (gid_pr == B_TRUE) {
ctx_gidp = &msgimplp->im_global_addr.ig_sender_gid;
if ((ctx_gidp->gid_prefix != gid->gid_prefix) ||
(ctx_gidp->gid_guid != gid->gid_guid)) {
msgimplp = msgimplp->im_msg_next;
continue;
}
} else {
IBMF_TRACE_5(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_find_msg, IBMF_TNF_TRACE, "",
"ibmf_i_find_msg(): %s, msgp = 0x%p, tid = 0x%p, "
"remote_lid = 0x%x, mgmt_class = 0x%x\n",
tnf_string, msg, "Comparing to msg",
tnf_opaque, msg, msgimplp,
tnf_opaque, tid, msgimplp->im_tid,
tnf_opaque, remote_lid,
msgimplp->im_local_addr.ia_remote_lid,
tnf_opaque, class, msgimplp->im_mgt_class);
if (msgimplp->im_local_addr.ia_remote_lid != lid) {
msgimplp = msgimplp->im_msg_next;
continue;
}
}
if ((msgimplp->im_tid != tid) ||
(msgimplp->im_mgt_class != mgt_class)) {
msgimplp = msgimplp->im_msg_next;
continue;
}
if (msgimplp->im_unsolicited == B_TRUE) {
ibmf_rmpp_ctx_t *rmpp_ctx;
ibmf_msg_bufs_t *msgbufp;
mutex_enter(&msgimplp->im_mutex);
rmpp_ctx = &msgimplp->im_rmpp_ctx;
if ((msgimplp->im_flags & IBMF_MSG_FLAGS_RECV_RMPP) &&
((rmpp_ctx->rmpp_state ==
IBMF_RMPP_STATE_RECEVR_ACTIVE) ||
(rmpp_ctx->rmpp_state ==
IBMF_RMPP_STATE_RECEVR_TERMINATE))) {
if (rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_ACK) {
mutex_exit(&msgimplp->im_mutex);
msgimplp = msgimplp->im_msg_next;
continue;
}
}
if (msgimplp->im_trans_state_flags ==
IBMF_TRANS_STATE_FLAG_RECV_ACTIVE) {
msgbufp = &msgimplp->im_msgbufs_recv;
if (msgbufp->im_bufs_mad_hdr->R_Method ==
r_method) {
mutex_exit(&msgimplp->im_mutex);
msg_found = B_TRUE;
break;
}
}
mutex_exit(&msgimplp->im_mutex);
}
if ((!(msgimplp->im_transp_op_flags &
IBMF_MSG_TRANS_FLAG_RMPP)) &&
(!(msgimplp->im_transp_op_flags &
IBMF_MSG_TRANS_FLAG_SEQ))) {
msgimplp = msgimplp->im_msg_next;
continue;
}
if (msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_SEQ) {
ibmf_msg_bufs_t *msgbufp;
mutex_enter(&msgimplp->im_mutex);
msgbufp = &msgimplp->im_msgbufs_send;
if ((msgbufp->im_bufs_mad_hdr->R_Method |
IBMF_RMPP_METHOD_RESP_BIT) == r_method) {
mutex_exit(&msgimplp->im_mutex);
msg_found = B_TRUE;
break;
}
mutex_exit(&msgimplp->im_mutex);
}
if (msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_RMPP) {
ibmf_rmpp_ctx_t *rmpp_ctx = &msgimplp->im_rmpp_ctx;
ibmf_msg_bufs_t *msgbufp;
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rmpp_ctx))
if ((rmpp_hdr != NULL) &&
(rmpp_hdr->rmpp_flags & IBMF_RMPP_FLAGS_ACTIVE)) {
if (!(msgimplp->im_transp_op_flags &
IBMF_MSG_TRANS_FLAG_SEQ)) {
if (rmpp_hdr->rmpp_type ==
IBMF_RMPP_TYPE_DATA) {
msgimplp =
msgimplp->im_msg_next;
continue;
}
}
if ((rmpp_ctx->rmpp_state ==
IBMF_RMPP_STATE_SENDER_ACTIVE) ||
(rmpp_ctx->rmpp_state ==
IBMF_RMPP_STATE_SENDER_SWITCH)) {
if (rmpp_hdr->rmpp_type ==
IBMF_RMPP_TYPE_DATA) {
msgimplp =
msgimplp->im_msg_next;
continue;
}
msgbufp = &msgimplp->im_msgbufs_send;
if ((msgbufp->im_bufs_mad_hdr->
R_Method & MAD_METHOD_MASK) !=
(r_method & MAD_METHOD_MASK)) {
msgimplp = msgimplp->
im_msg_next;
continue;
}
}
if ((rmpp_ctx->rmpp_state ==
IBMF_RMPP_STATE_RECEVR_ACTIVE) ||
(rmpp_ctx->rmpp_state ==
IBMF_RMPP_STATE_RECEVR_TERMINATE)) {
if (rmpp_hdr->rmpp_type ==
IBMF_RMPP_TYPE_ACK) {
msgimplp =
msgimplp->im_msg_next;
continue;
}
msgbufp = &msgimplp->im_msgbufs_recv;
if (msgbufp->im_bufs_mad_hdr->
R_Method != r_method) {
msgimplp = msgimplp->
im_msg_next;
continue;
}
}
}
}
if ((msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_SEQ) &&
!(msgimplp->im_transp_op_flags &
IBMF_MSG_TRANS_FLAG_RMPP)) {
ibmf_msg_bufs_t *msgbufp;
mutex_enter(&msgimplp->im_mutex);
msgbufp = &msgimplp->im_msgbufs_send;
mutex_exit(&msgimplp->im_mutex);
if (msgbufp->im_bufs_mad_hdr->
R_Method == r_method) {
msgimplp = msgimplp-> im_msg_next;
continue;
}
}
msg_found = B_TRUE;
break;
}
if (msg_found == B_TRUE) {
mutex_enter(&msgimplp->im_mutex);
IBMF_MSG_INCR_REFCNT(msgimplp);
IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_find_msg, IBMF_TNF_TRACE, "",
"ibmf_i_find_msg(): %s, msgp = 0x%p, ref_cnt = 0x%d\n",
tnf_string, msg, "Found message. Inc ref count",
tnf_opaque, msgimplp, msgimplp,
tnf_uint, ref_count, msgimplp->im_ref_count);
mutex_exit(&msgimplp->im_mutex);
}
mutex_exit(&clientp->ic_msg_mutex);
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_find_msg_end, IBMF_TNF_TRACE, "",
"ibmf_i_find_msg() exit, msgp = 0x%p\n", tnf_opaque, msg, msgimplp);
return (msgimplp);
}
boolean_t
ibmf_i_find_msg_client(ibmf_client_t *clp, ibmf_msg_impl_t *msgimplp,
boolean_t inc_refcnt)
{
ibmf_msg_impl_t *msgp;
boolean_t found = B_FALSE;
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_find_msg_client_start, IBMF_TNF_TRACE, "",
"ibmf_i_find_msg_client(): clientp = 0x%p, msgp = 0x%p\n",
tnf_opaque, clientp, clp, tnf_opaque, msg, msgimplp);
mutex_enter(&clp->ic_msg_mutex);
msgp = clp->ic_msg_list;
while (msgp != NULL) {
if (msgp == msgimplp) {
mutex_enter(&msgimplp->im_mutex);
if (inc_refcnt == B_TRUE)
IBMF_MSG_INCR_REFCNT(msgimplp);
IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_find_msg_client, IBMF_TNF_TRACE, "",
"ibmf_i_find_msg_client(): %s, msgp = 0x%p, "
"ref_cnt = 0x%d\n",
tnf_string, msg, "Found message. Inc ref count",
tnf_opaque, msgimplp, msgimplp,
tnf_uint, ref_count, msgimplp->im_ref_count);
mutex_exit(&msgimplp->im_mutex);
found = B_TRUE;
break;
}
msgp = msgp->im_msg_next;
}
if (found == B_FALSE) {
msgp = clp->ic_term_msg_list;
while (msgp != NULL) {
if (msgp == msgimplp) {
mutex_enter(&msgimplp->im_mutex);
if (inc_refcnt == B_TRUE)
IBMF_MSG_INCR_REFCNT(msgimplp);
IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_find_msg_client, IBMF_TNF_TRACE, "",
"ibmf_i_find_msg_client(): %s, "
"msgp = 0x%p, ref_cnt = 0x%d\n", tnf_string,
msg, "Found message. Inc ref count",
tnf_opaque, msgimplp, msgimplp, tnf_uint,
ref_count, msgimplp->im_ref_count);
mutex_exit(&msgimplp->im_mutex);
found = B_TRUE;
break;
}
msgp = msgp->im_msg_next;
}
}
mutex_exit(&clp->ic_msg_mutex);
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_find_msg_client_end, IBMF_TNF_TRACE, "",
"ibmf_i_find_msg_client() exit\n");
return (found);
}
int
ibmf_setup_recvbuf_on_error(ibmf_msg_impl_t *msgimplp, uchar_t *mad)
{
size_t offset;
uint32_t cl_hdr_sz, cl_hdr_off;
ib_mad_hdr_t *mad_hdr;
uchar_t *msgbufp;
ibmf_client_t *clientp = (ibmf_client_t *)msgimplp->im_client;
ASSERT(msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL);
msgimplp->im_msgbufs_recv.im_bufs_mad_hdr =
(ib_mad_hdr_t *)kmem_zalloc(IBMF_MAD_SIZE, KM_NOSLEEP);
if (msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL) {
IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_setup_recvbuf_on_error, IBMF_TNF_ERROR, "",
"ibmf_setup_recvbuf_on_error(): %s\n", tnf_string, msg,
"recv buf mem allocation failure");
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_setup_recvbuf_on_error_end, IBMF_TNF_TRACE, "",
"ibmf_setup_recvbuf_on_error() exit\n");
return (IBMF_NO_RESOURCES);
}
mutex_enter(&clientp->ic_kstat_mutex);
IBMF_ADD32_KSTATS(clientp, recv_bufs_alloced, 1);
mutex_exit(&clientp->ic_kstat_mutex);
mad_hdr = (ib_mad_hdr_t *)mad;
ibmf_i_mgt_class_to_hdr_sz_off(mad_hdr->MgmtClass, &cl_hdr_sz,
&cl_hdr_off);
msgbufp = (uchar_t *)msgimplp->im_msgbufs_recv.im_bufs_mad_hdr;
bcopy((const void *)mad, (void *)msgbufp,
sizeof (ib_mad_hdr_t) + cl_hdr_off + cl_hdr_sz);
offset = sizeof (ib_mad_hdr_t) + cl_hdr_off;
if (cl_hdr_sz == 0) {
msgimplp->im_msgbufs_recv.im_bufs_cl_hdr = NULL;
} else {
msgimplp->im_msgbufs_recv.im_bufs_cl_hdr =
(void *)(msgbufp + offset);
}
msgimplp->im_msgbufs_recv.im_bufs_cl_hdr_len = cl_hdr_sz;
offset += cl_hdr_sz;
msgimplp->im_msgbufs_recv.im_bufs_cl_data = (void *)(msgbufp + offset);
msgimplp->im_msgbufs_recv.im_bufs_cl_data_len = IBMF_MAD_SIZE -
sizeof (ib_mad_hdr_t) - cl_hdr_off - cl_hdr_sz;
return (IBMF_SUCCESS);
}