#include <sys/ib/mgt/ibmf/ibmf_impl.h>
extern int ibmf_trace_level;
void
ibmf_i_terminate_transaction(ibmf_client_t *clientp, ibmf_msg_impl_t *msgimplp,
uint32_t status)
{
IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_terminate_transaction_start, IBMF_TNF_TRACE, "",
"ibmf_i_terminate_transaction(): clientp = 0x%p, msgp = 0x%p, "
"status = 0x%x\n", tnf_opaque, clientp, clientp,
tnf_opaque, msg, msgimplp, tnf_uint, status, status);
ASSERT(MUTEX_HELD(&msgimplp->im_mutex));
msgimplp->im_msg_status = status;
ibmf_i_unset_timer(msgimplp, IBMF_TRANS_TIMER);
if (msgimplp->im_unsolicited == B_TRUE) {
msgimplp->im_trans_state_flags |= IBMF_TRANS_STATE_FLAG_DONE;
} else {
IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_terminate_transaction, IBMF_TNF_TRACE, "",
"ibmf_i_terminate_transaction(): %s, "
"trans_state_flags = 0x%x, msg_flags = 0x%x\n",
tnf_string, msg, "solicted message callback",
tnf_opaque, trans_state_flags,
msgimplp->im_trans_state_flags,
tnf_opaque, flags, msgimplp->im_flags);
msgimplp->im_trans_state_flags |=
IBMF_TRANS_STATE_FLAG_RECV_DONE;
if (msgimplp->im_trans_state_flags &
IBMF_TRANS_STATE_FLAG_SEND_DONE) {
msgimplp->im_trans_state_flags |=
IBMF_TRANS_STATE_FLAG_DONE;
}
}
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_terminate_transaction_end, IBMF_TNF_TRACE, "",
"ibmf_i_terminate_transaction() exit\n");
}
void
ibmf_i_notify_client(ibmf_msg_impl_t *msgimplp)
{
ibmf_client_t *clientp;
ibmf_msg_cb_t async_cb;
void *async_cb_arg;
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_notify_client_start,
IBMF_TNF_TRACE, "", "ibmf_i_notify_client(): msgp = 0x%p\n",
tnf_opaque, msgimplp, msgimplp);
clientp = msgimplp->im_client;
mutex_enter(&msgimplp->im_mutex);
ASSERT(msgimplp->im_trans_state_flags & IBMF_TRANS_STATE_FLAG_DONE);
if (msgimplp->im_ref_count != 0) {
mutex_exit(&msgimplp->im_mutex);
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_notify_client_err, IBMF_TNF_TRACE,
"", "ibmf_i_notify_client(): %s\n",
tnf_string, msg, "message reference count != 0");
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_notify_client_end, IBMF_TNF_TRACE, "",
"ibmf_i_notify_client() exit\n");
return;
}
mutex_exit(&msgimplp->im_mutex);
if (msgimplp->im_ibmf_ud_dest != NULL) {
ibmf_i_free_ud_dest(clientp, msgimplp);
ibmf_i_clean_ud_dest_list(clientp->ic_myci, B_FALSE);
}
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msgimplp))
if (msgimplp->im_unsolicited == B_TRUE) {
if (msgimplp->im_msg_status != IBMF_SUCCESS) {
if (msgimplp->im_qp_hdl == IBMF_QP_HANDLE_DEFAULT) {
mutex_enter(&clientp->ic_mutex);
IBMF_RECV_CB_CLEANUP(clientp);
mutex_exit(&clientp->ic_mutex);
} else {
ibmf_alt_qp_t *qpp =
(ibmf_alt_qp_t *)msgimplp->im_qp_hdl;
mutex_enter(&qpp->isq_mutex);
IBMF_ALT_RECV_CB_CLEANUP(qpp);
mutex_exit(&qpp->isq_mutex);
}
IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_i_notify_client_err, IBMF_TNF_ERROR, "",
"ibmf_i_notify_client(): %s, status = %d\n",
tnf_string, msg, "message status not success",
tnf_opaque, status, msgimplp->im_msg_status);
ibmf_i_free_msg(msgimplp);
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_notify_client_end, IBMF_TNF_TRACE, "",
"ibmf_i_notify_client() exit\n");
return;
}
if (msgimplp->im_qp_hdl == IBMF_QP_HANDLE_DEFAULT) {
mutex_enter(&clientp->ic_mutex);
if ((clientp->ic_recv_cb == NULL) ||
(clientp->ic_flags & IBMF_CLIENT_TEAR_DOWN_CB)) {
IBMF_RECV_CB_CLEANUP(clientp);
mutex_exit(&clientp->ic_mutex);
ibmf_i_free_msg(msgimplp);
IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_i_notify_client_err, IBMF_TNF_ERROR,
"", "ibmf_i_notify_client(): %s\n",
tnf_string, msg,
"ibmf_tear_down_recv_cb already occurred");
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_notify_client_end,
IBMF_TNF_TRACE, "",
"ibmf_i_notify_client() exit\n");
return;
}
clientp->ic_msgs_alloced++;
mutex_enter(&clientp->ic_kstat_mutex);
IBMF_ADD32_KSTATS(clientp, msgs_alloced, 1);
mutex_exit(&clientp->ic_kstat_mutex);
async_cb = clientp->ic_recv_cb;
async_cb_arg = clientp->ic_recv_cb_arg;
mutex_exit(&clientp->ic_mutex);
async_cb((ibmf_handle_t)clientp, (ibmf_msg_t *)msgimplp,
async_cb_arg);
mutex_enter(&clientp->ic_mutex);
IBMF_RECV_CB_CLEANUP(clientp);
mutex_exit(&clientp->ic_mutex);
} else {
ibmf_alt_qp_t *qpp =
(ibmf_alt_qp_t *)msgimplp->im_qp_hdl;
mutex_enter(&qpp->isq_mutex);
if ((qpp->isq_recv_cb == NULL) ||
(qpp->isq_flags & IBMF_CLIENT_TEAR_DOWN_CB)) {
IBMF_ALT_RECV_CB_CLEANUP(qpp);
mutex_exit(&qpp->isq_mutex);
ibmf_i_free_msg(msgimplp);
IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_i_notify_client_err, IBMF_TNF_ERROR,
"", "ibmf_i_notify_client(): %s\n",
tnf_string, msg,
"ibmf_tear_down_recv_cb already occurred");
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_notify_client_end,
IBMF_TNF_TRACE, "",
"ibmf_i_notify_client() exit\n");
return;
}
async_cb = qpp->isq_recv_cb;
async_cb_arg = qpp->isq_recv_cb_arg;
mutex_exit(&qpp->isq_mutex);
mutex_enter(&clientp->ic_mutex);
clientp->ic_msgs_alloced++;
mutex_exit(&clientp->ic_mutex);
mutex_enter(&clientp->ic_kstat_mutex);
IBMF_ADD32_KSTATS(clientp, msgs_alloced, 1);
mutex_exit(&clientp->ic_kstat_mutex);
async_cb((ibmf_handle_t)clientp, (ibmf_msg_t *)msgimplp,
async_cb_arg);
mutex_enter(&qpp->isq_mutex);
IBMF_ALT_RECV_CB_CLEANUP(qpp);
mutex_exit(&qpp->isq_mutex);
}
} else {
if (msgimplp->im_trans_cb == NULL) {
mutex_enter(&msgimplp->im_mutex);
if (msgimplp->im_trans_state_flags &
IBMF_TRANS_STATE_FLAG_WAIT) {
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_notify_client, IBMF_TNF_TRACE, "",
"ibmf_i_notify_client(): %s, msg = 0x%p\n",
tnf_string, msg, "Awaking thread",
tnf_opaque, msgimplp, msgimplp);
cv_signal(&msgimplp->im_trans_cv);
} else {
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_notify_client, IBMF_TNF_TRACE, "",
"ibmf_i_notify_client(): %s, msg = 0x%p\n",
tnf_string, msg, "Notify client, no wait",
tnf_opaque, msgimplp, msgimplp);
}
msgimplp->im_trans_state_flags |=
IBMF_TRANS_STATE_FLAG_SIGNALED;
mutex_exit(&msgimplp->im_mutex);
} else {
mutex_enter(&msgimplp->im_mutex);
msgimplp->im_flags &= ~IBMF_MSG_FLAGS_BUSY;
mutex_exit(&msgimplp->im_mutex);
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_notify_client, IBMF_TNF_TRACE, "",
"ibmf_i_notify_client(): %s, msg = 0x%p\n",
tnf_string, msg, "No thread is blocking",
tnf_opaque, msgimplp, msgimplp);
if (msgimplp->im_trans_cb != NULL) {
msgimplp->im_trans_cb(
(ibmf_handle_t)clientp,
(ibmf_msg_t *)msgimplp,
msgimplp->im_trans_cb_arg);
}
}
}
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_notify_client_end,
IBMF_TNF_TRACE, "", "ibmf_i_notify_client() exit\n");
}
void
ibmf_i_notify_sequence(ibmf_client_t *clientp, ibmf_msg_impl_t *msgimplp,
int msg_flags)
{
int status;
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_notify_sequence_start, IBMF_TNF_TRACE, "",
"ibmf_i_notify_sequence() enter, clientp = %p, msgimplp = %p\n",
tnf_opaque, clientp, clientp, tnf_opaque, msgimplp, msgimplp);
if (msg_flags & IBMF_MSG_FLAGS_TERMINATION) {
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_notify_sequence,
IBMF_TNF_TRACE, "", "ibmf_i_notify_sequence(): %s, "
"msgimplp = %p\n", tnf_string, msg,
"IBMF_MSG_FLAGS_TERMINATION already set",
tnf_opaque, msgimplp, msgimplp);
return;
}
if (msg_flags & IBMF_MSG_FLAGS_SET_TERMINATION) {
status = ibmf_setup_term_ctx(clientp, msgimplp);
if (status != IBMF_SUCCESS) {
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_notify_sequence, IBMF_TNF_TRACE,
"", "ibmf_i_notify_sequence(): %s, "
"msgimplp = %p\n", tnf_string, msg,
"ibmf_setup_term_ctx() failed,"
"reversing to regular termination",
tnf_opaque, msgimplp, msgimplp);
mutex_enter(&msgimplp->im_mutex);
ibmf_i_set_timer(ibmf_i_recv_timeout, msgimplp,
IBMF_RESP_TIMER);
msgimplp->im_trans_state_flags &=
~IBMF_TRANS_STATE_FLAG_DONE;
msgimplp->im_trans_state_flags &=
~IBMF_TRANS_STATE_FLAG_RECV_DONE;
mutex_exit(&msgimplp->im_mutex);
ibmf_i_client_add_msg(clientp, msgimplp);
} else {
ibmf_i_notify_client(msgimplp);
}
} else {
ibmf_i_notify_client(msgimplp);
}
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_notify_sequence_end, IBMF_TNF_TRACE, "",
"ibmf_i_notify_sequence() exit, msgimplp = %p\n",
tnf_opaque, msgimplp, msgimplp);
}