#include <sys/ib/mgt/ibmf/ibmf_impl.h>
extern ibmf_state_t *ibmf_statep;
extern int ibmf_trace_level;
#define IBMF_BUF_PKTS 10
static void ibmf_i_rmpp_sender_active_flow(ibmf_client_t *clientp,
ibmf_qp_handle_t qp_hdl, ibmf_msg_impl_t *msgimplp, uchar_t *mad);
static void ibmf_i_rmpp_sender_switch_flow(ibmf_client_t *clientp,
ibmf_qp_handle_t qp_hdl, ibmf_msg_impl_t *msgimplp, uchar_t *mad);
static void ibmf_i_rmpp_recvr_flow_main(ibmf_client_t *clientp,
ibmf_qp_handle_t qp_hdl, ibmf_msg_impl_t *msgimplp, uchar_t *mad);
static void ibmf_i_rmpp_recvr_active_flow(ibmf_client_t *clientp,
ibmf_qp_handle_t qp_hdl, ibmf_msg_impl_t *msgimplp, uchar_t *mad);
static void ibmf_i_rmpp_recvr_term_flow(ibmf_client_t *clientp,
ibmf_qp_handle_t qp_hdl, ibmf_msg_impl_t *msgimplp, uchar_t *mad);
static boolean_t ibmf_i_is_valid_rmpp_status(ibmf_rmpp_hdr_t *rmpp_hdr);
boolean_t
ibmf_i_is_rmpp(ibmf_client_t *clientp, ibmf_qp_handle_t ibmf_qp_handle)
{
ibmf_alt_qp_t *qpp = (ibmf_alt_qp_t *)ibmf_qp_handle;
boolean_t is_rmpp;
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_is_rmpp_start,
IBMF_TNF_TRACE, "", "ibmf_i_is_rmpp(): clientp = %p, "
"ibmf_qp_handle = 0x%p\n", tnf_opaque, clientp, clientp,
tnf_opaque, ibmf_qp_handle, ibmf_qp_handle);
if ((clientp->ic_reg_flags & IBMF_REG_FLAG_RMPP) == 0) {
is_rmpp = B_FALSE;
} else if ((ibmf_qp_handle != IBMF_QP_HANDLE_DEFAULT) &&
(qpp->isq_supports_rmpp == B_FALSE)) {
is_rmpp = B_FALSE;
} else {
is_rmpp = B_TRUE;
}
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_is_rmpp_end,
IBMF_TNF_TRACE, "", "ibmf_i_is_rmpp() exit, is_rmpp = %d\n",
tnf_uint, is_rmpp, is_rmpp);
return (is_rmpp);
}
static void
ibmf_i_rmpp_sender_active_flow(ibmf_client_t *clientp, ibmf_qp_handle_t qp_hdl,
ibmf_msg_impl_t *msgimplp, uchar_t *mad)
{
ibmf_rmpp_ctx_t *rmpp_ctx = &msgimplp->im_rmpp_ctx;
ibmf_rmpp_hdr_t *rmpp_hdr;
uint32_t abort_status;
int status;
IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_sender_active_flow_start, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_active_flow(): clientp = 0x%p, qp_hdl = 0x%p, "
"msgp = 0x%p, madp = 0x%p\n", tnf_opaque, clientp, clientp,
tnf_opaque, qp_hdl, qp_hdl, tnf_opaque, msg, msgimplp,
tnf_opaque, mad, mad);
rmpp_hdr = (ibmf_rmpp_hdr_t *)(mad + sizeof (ib_mad_hdr_t));
if (rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_DATA) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_sender_active_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_active_flow(): %s\n", tnf_string, msg,
"Data packet received, discarding it");
ibmf_i_send_rmpp_window(msgimplp, IBMF_NO_BLOCK);
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_sender_active_flow_end, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_active_flow() exit\n");
return;
}
if (rmpp_hdr->rmpp_type != IBMF_RMPP_TYPE_ACK) {
if ((rmpp_hdr->rmpp_type != IBMF_RMPP_TYPE_STOP) &&
(rmpp_hdr->rmpp_type != IBMF_RMPP_TYPE_ABORT)) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_i_rmpp_sender_active_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_active_flow(): %s\n",
tnf_string, msg,
"Unrecognized packet received, sending ABORT");
status = ibmf_i_send_rmpp(msgimplp,
IBMF_RMPP_TYPE_ABORT, IBMF_RMPP_STATUS_BADT,
0, 0, IBMF_NO_BLOCK);
if (status != IBMF_SUCCESS) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_i_rmpp_sender_active_flow,
IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_active_flow(): %s\n",
tnf_string, msg, "RMPP ABORT send failed");
msgimplp->im_trans_state_flags |=
IBMF_TRANS_STATE_FLAG_SEND_DONE;
}
mutex_enter(&clientp->ic_kstat_mutex);
IBMF_ADD32_KSTATS(clientp, rmpp_errors, 1);
mutex_exit(&clientp->ic_kstat_mutex);
} else {
abort_status = rmpp_hdr->rmpp_status;
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_i_rmpp_sender_active_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_active_flow(): %s, "
"status = %d\n", tnf_string, msg,
"STOP or ABORT packet received, terminating",
tnf_uint, abort_status, abort_status);
}
rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
msgimplp->im_trans_state_flags |=
IBMF_TRANS_STATE_FLAG_SEND_DONE;
ibmf_i_set_timer(ibmf_i_err_terminate_timeout, msgimplp,
IBMF_RESP_TIMER);
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_sender_active_flow_end, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_active_flow() exit\n");
return;
}
IBMF_TRACE_5(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_rmpp_sender_active_flow,
IBMF_TNF_TRACE, "", "ibmf_i_rmpp_sender_active_flow(): %s, "
"msgp = 0x%p, recvd seg = %d wl = %d wf = %d\n",
tnf_string, msg, "ACK packet received",
tnf_opaque, msgp, msgimplp, tnf_uint, recvd_seg,
b2h32(rmpp_hdr->rmpp_segnum), tnf_uint, wl, rmpp_ctx->rmpp_wl,
tnf_uint, wf, rmpp_ctx->rmpp_wf);
if (b2h32(rmpp_hdr->rmpp_segnum) > rmpp_ctx->rmpp_wl) {
status = ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ABORT,
IBMF_RMPP_STATUS_S2B, 0, 0, IBMF_NO_BLOCK);
if (status != IBMF_SUCCESS) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_i_rmpp_sender_active_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_active_flow(): %s\n",
tnf_string, msg, "RMPP ABORT send failed");
msgimplp->im_trans_state_flags |=
IBMF_TRANS_STATE_FLAG_SEND_DONE;
}
mutex_enter(&clientp->ic_kstat_mutex);
IBMF_ADD32_KSTATS(clientp, rmpp_errors, 1);
mutex_exit(&clientp->ic_kstat_mutex);
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_i_rmpp_sender_active_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_active_flow(): %s\n",
tnf_string, msg, "Segnum > WL");
rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
ibmf_i_set_timer(ibmf_i_err_terminate_timeout,
msgimplp, IBMF_RESP_TIMER);
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_sender_active_flow_end, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_active_flow() exit\n");
return;
}
if (b2h32(rmpp_hdr->rmpp_segnum) < rmpp_ctx->rmpp_wf) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_sender_active_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_active_flow(): %s\n",
tnf_string, msg, "Segnum < WF");
ibmf_i_send_rmpp_window(msgimplp, IBMF_NO_BLOCK);
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_sender_active_flow_end, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_active_flow() exit\n");
return;
}
if (b2h32(rmpp_hdr->rmpp_pyldlen_nwl) < rmpp_ctx->rmpp_wl) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_i_rmpp_sender_active_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_active_flow(): %s\n",
tnf_string, msg, "NWL < WL");
status = ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ABORT,
IBMF_RMPP_STATUS_W2S, 0, 0, IBMF_NO_BLOCK);
if (status != IBMF_SUCCESS) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_i_rmpp_sender_active_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_active_flow(): %s\n",
tnf_string, msg, "RMPP ABORT send failed");
msgimplp->im_trans_state_flags |=
IBMF_TRANS_STATE_FLAG_SEND_DONE;
}
mutex_enter(&clientp->ic_kstat_mutex);
IBMF_ADD32_KSTATS(clientp, rmpp_errors, 1);
mutex_exit(&clientp->ic_kstat_mutex);
rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
ibmf_i_set_timer(ibmf_i_err_terminate_timeout,
msgimplp, IBMF_RESP_TIMER);
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_sender_active_flow_end, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_active_flow() exit\n");
return;
}
if (b2h32(rmpp_hdr->rmpp_segnum) == rmpp_ctx->rmpp_num_pkts) {
IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_sender_active_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_active_flow(): %s, msgp = 0x%p, "
"double-sided = %d\n", tnf_string, msg, "Last packet",
tnf_opaque, msgimplp, msgimplp,
tnf_opaque, double_sided, rmpp_ctx->rmpp_is_ds);
if (rmpp_ctx->rmpp_is_ds) {
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_sender_active_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_active_flow(): %s, "
"msgp = 0x%p\n", tnf_string, msg,
"Doublesided,sending ACK and switching to receiver",
tnf_opaque, msgimplp, msgimplp);
rmpp_ctx->rmpp_is_ds = B_FALSE;
rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_SENDER_SWITCH;
rmpp_ctx->rmpp_wf = 1;
rmpp_ctx->rmpp_wl = 1;
rmpp_ctx->rmpp_es = 1;
(void) ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ACK,
IBMF_RMPP_STATUS_NORMAL, 0, 1, IBMF_NO_BLOCK);
ibmf_i_set_timer(ibmf_i_send_timeout,
msgimplp, IBMF_RESP_TIMER);
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_sender_active_flow_end,
IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_active_flow() exit\n");
return;
}
rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_DONE;
ibmf_i_terminate_transaction(clientp, msgimplp, IBMF_SUCCESS);
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_sender_active_flow_end, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_active_flow() exit\n");
return;
}
rmpp_ctx->rmpp_wf = b2h32(rmpp_hdr->rmpp_segnum) + 1;
rmpp_ctx->rmpp_ns = b2h32(rmpp_hdr->rmpp_segnum) + 1;
rmpp_ctx->rmpp_wl =
(rmpp_ctx->rmpp_num_pkts < b2h32(rmpp_hdr->rmpp_pyldlen_nwl)) ?
rmpp_ctx->rmpp_num_pkts : b2h32(rmpp_hdr->rmpp_pyldlen_nwl);
IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_rmpp_sender_active_flow,
IBMF_TNF_TRACE, "", "ibmf_i_rmpp_sender_active_flow(): %s, "
"wf = %d, wl = %d, ns = %d\n",
tnf_string, msg, "sending next window",
tnf_uint, wf, rmpp_ctx->rmpp_wf, tnf_uint, wl, rmpp_ctx->rmpp_wl,
tnf_uint, ns, rmpp_ctx->rmpp_ns);
ibmf_i_send_rmpp_window(msgimplp, IBMF_NO_BLOCK);
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_sender_active_flow_end, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_active_flow() exit\n");
}
static void
ibmf_i_rmpp_sender_switch_flow(ibmf_client_t *clientp, ibmf_qp_handle_t qp_hdl,
ibmf_msg_impl_t *msgimplp, uchar_t *mad)
{
ibmf_rmpp_ctx_t *rmpp_ctx = &msgimplp->im_rmpp_ctx;
ibmf_rmpp_hdr_t *rmpp_hdr;
int status;
IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_sender_switch_flow_start, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_switch_flow(): clientp = 0x%p, qp_hdl = 0x%p, "
"msgp = 0x%p, madp = 0x%p\n", tnf_opaque, clientp, clientp,
tnf_opaque, qp_hdl, qp_hdl, tnf_opaque, msg, msgimplp,
tnf_opaque, mad, mad);
rmpp_hdr = (ibmf_rmpp_hdr_t *)(mad + sizeof (ib_mad_hdr_t));
if (rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_ACK) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_sender_switch_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_switch_flow(): %s\n", tnf_string, msg,
"ACK packet received, sending ACK");
(void) ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ACK,
IBMF_RMPP_STATUS_NORMAL, 0, 1, IBMF_NO_BLOCK);
ibmf_i_set_timer(ibmf_i_send_timeout, msgimplp,
IBMF_RESP_TIMER);
} else if (rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_DATA) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_sender_switch_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_switch_flow(): %s\n", tnf_string, msg,
"DATA packet received, processing packet");
msgimplp->im_flags |= IBMF_MSG_FLAGS_RECV_RMPP;
ibmf_i_rmpp_recvr_flow_main(clientp, qp_hdl, msgimplp, mad);
} else {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_i_rmpp_sender_switch_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_switch_flow(): %s\n", tnf_string, msg,
"Unexpected packet received, sending ABORT BADT");
status = ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ABORT,
IBMF_RMPP_STATUS_BADT, 0, 0, IBMF_NO_BLOCK);
if (status != IBMF_SUCCESS) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_i_rmpp_sender_switch_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_switch_flow(): %s\n",
tnf_string, msg, "RMPP ABORT send failed");
msgimplp->im_trans_state_flags |=
IBMF_TRANS_STATE_FLAG_SEND_DONE;
}
mutex_enter(&clientp->ic_kstat_mutex);
IBMF_ADD32_KSTATS(clientp, rmpp_errors, 1);
mutex_exit(&clientp->ic_kstat_mutex);
rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
ibmf_i_set_timer(ibmf_i_err_terminate_timeout,
msgimplp, IBMF_RESP_TIMER);
}
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_sender_switch_flow_end, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_sender_switch_flow() exit\n");
}
static void
ibmf_i_rmpp_recvr_flow_main(ibmf_client_t *clientp, ibmf_qp_handle_t qp_hdl,
ibmf_msg_impl_t *msgimplp, uchar_t *mad)
{
ibmf_rmpp_ctx_t *rmpp_ctx = &msgimplp->im_rmpp_ctx;
ibmf_rmpp_hdr_t *rmpp_hdr;
ib_mad_hdr_t *mad_hdr;
uchar_t *msgbufp;
uchar_t *datap;
uint32_t data_sz, offset, num_pkts;
uint32_t cl_hdr_sz, cl_data_sz, cl_hdr_off, cl_hdrdata_sz;
size_t buf_sz;
int status;
IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_recvr_flow_main_start, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main(): clientp = 0x%p, qp_hdl = 0x%p, "
"msgp = 0x%p, madp = 0x%p\n", tnf_opaque, clientp, clientp,
tnf_opaque, qp_hdl, qp_hdl, tnf_opaque, msg, msgimplp,
tnf_opaque, mad, mad);
rmpp_hdr = (ibmf_rmpp_hdr_t *)(mad + sizeof (ib_mad_hdr_t));
IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_rmpp_recvr_flow_main,
IBMF_TNF_TRACE, "", "ibmf_i_rmpp_recvr_flow_main(): "
"segnum = %d, es = %d, wl = %d\n", tnf_uint, segnum,
b2h32(rmpp_hdr->rmpp_segnum), tnf_uint, es, rmpp_ctx->rmpp_es,
tnf_uint, wl, rmpp_ctx->rmpp_wl);
if (b2h32(rmpp_hdr->rmpp_segnum) != rmpp_ctx->rmpp_es) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main(): %s\n", tnf_string, msg,
"Unexpected segment number, discarding packet");
if (msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL) {
status = ibmf_setup_recvbuf_on_error(msgimplp, mad);
if (status != IBMF_SUCCESS) {
IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L2,
ibmf_i_rmpp_recvr_flow_main_err,
IBMF_TNF_ERROR, "",
"ibmf_i_rmpp_recvr_flow_main(): %s\n",
tnf_string, msg,
"ibmf_setup_recvbuf_on_error() failed");
return;
}
}
if (rmpp_ctx->rmpp_es > 1) {
(void) ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ACK,
IBMF_RMPP_STATUS_NORMAL, rmpp_ctx->rmpp_es - 1,
rmpp_ctx->rmpp_es - 1 + IBMF_RMPP_DEFAULT_WIN_SZ,
IBMF_NO_BLOCK);
}
if (rmpp_ctx->rmpp_es == 1) {
ibmf_i_set_timer(ibmf_i_send_timeout, msgimplp,
IBMF_RESP_TIMER);
}
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_recvr_flow_main_end, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main() exit\n");
return;
}
mad_hdr = (ib_mad_hdr_t *)mad;
ibmf_i_mgt_class_to_hdr_sz_off(mad_hdr->MgmtClass, &cl_hdr_sz,
&cl_hdr_off);
if ((rmpp_hdr->rmpp_flags & IBMF_RMPP_FLAGS_FIRST_PKT) ||
(b2h32(rmpp_hdr->rmpp_segnum) == 1)) {
if (((rmpp_hdr->rmpp_flags & IBMF_RMPP_FLAGS_FIRST_PKT) == 0) ||
(b2h32(rmpp_hdr->rmpp_segnum) != 1)) {
if (msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL) {
status = ibmf_setup_recvbuf_on_error(msgimplp,
mad);
if (status != IBMF_SUCCESS) {
IBMF_TRACE_1(IBMF_TNF_NODEBUG,
DPRINT_L2,
ibmf_i_rmpp_recvr_flow_main_err,
IBMF_TNF_ERROR, "",
"ibmf_i_rmpp_recvr_flow_main(): "
"%s\n", tnf_string, msg,
"ibmf_setup_recvbuf_on_error() "
"failed");
return;
}
}
status = ibmf_i_send_rmpp(msgimplp,
IBMF_RMPP_TYPE_ABORT, IBMF_RMPP_STATUS_IFSN,
0, 0, IBMF_NO_BLOCK);
if (status != IBMF_SUCCESS) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_i_rmpp_recvr_flow_main,
IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main(): %s\n",
tnf_string, msg, "RMPP ABORT send failed");
msgimplp->im_trans_state_flags |=
IBMF_TRANS_STATE_FLAG_SEND_DONE;
}
mutex_enter(&clientp->ic_kstat_mutex);
IBMF_ADD32_KSTATS(clientp, rmpp_errors, 1);
mutex_exit(&clientp->ic_kstat_mutex);
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main(): %s\n",
tnf_string, msg, "Inconsistent first and segment "
"number detected, sending ABORT IFSN");
rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
ibmf_i_unset_timer(msgimplp, IBMF_TRANS_TIMER);
ibmf_i_set_timer(ibmf_i_err_terminate_timeout,
msgimplp, IBMF_RESP_TIMER);
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_recvr_flow_main_end, IBMF_TNF_TRACE,
"", "ibmf_i_rmpp_recvr_flow_main() exit\n");
return;
}
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main(): %s\n", tnf_string, msg,
"Segment number 1 received:", tnf_opaque, msgp, msgimplp);
cl_data_sz = MAD_SIZE_IN_BYTES -
sizeof (ib_mad_hdr_t) - cl_hdr_off - cl_hdr_sz;
cl_hdrdata_sz = MAD_SIZE_IN_BYTES -
sizeof (ib_mad_hdr_t) - cl_hdr_off;
buf_sz = b2h32(rmpp_hdr->rmpp_pyldlen_nwl);
if ((buf_sz % cl_hdrdata_sz) != 0)
num_pkts = (buf_sz / cl_hdrdata_sz) + 1;
else {
if (buf_sz > 0)
num_pkts = buf_sz / cl_hdrdata_sz;
else
num_pkts = 1;
}
if (b2h32(rmpp_hdr->rmpp_pyldlen_nwl) != 0) {
msgimplp->im_msgbufs_recv.im_bufs_cl_data_len =
rmpp_ctx->rmpp_pyld_len =
b2h32(rmpp_hdr->rmpp_pyldlen_nwl) -
(num_pkts * cl_hdr_sz);
} else {
msgimplp->im_msgbufs_recv.im_bufs_cl_data_len =
rmpp_ctx->rmpp_pyld_len =
IBMF_BUF_PKTS * cl_data_sz;
rmpp_ctx->rmpp_flags |= IBMF_CTX_RMPP_FLAGS_DYN_PYLD;
}
ASSERT(msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL);
msgimplp->im_msgbufs_recv.im_bufs_mad_hdr =
(ib_mad_hdr_t *)kmem_zalloc(sizeof (ib_mad_hdr_t) +
cl_hdr_off + cl_hdr_sz + rmpp_ctx->rmpp_pyld_len,
KM_NOSLEEP);
if (msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main(): %s\n",
tnf_string, msg,
"mem allocation failure (known rmpp payload)");
ibmf_i_terminate_transaction(
msgimplp->im_client, msgimplp,
IBMF_NO_MEMORY);
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_recvr_flow_main_end, IBMF_TNF_TRACE,
"", "ibmf_i_rmpp_recvr_flow_main() exit\n");
return;
}
mutex_enter(&clientp->ic_kstat_mutex);
IBMF_ADD32_KSTATS(clientp, recv_bufs_alloced, 1);
mutex_exit(&clientp->ic_kstat_mutex);
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);
rmpp_ctx->rmpp_data_offset = 0;
cl_data_sz = MAD_SIZE_IN_BYTES -
sizeof (ib_mad_hdr_t) - cl_hdr_off - cl_hdr_sz;
rmpp_ctx->rmpp_pkt_data_sz = cl_data_sz;
if (rmpp_ctx->rmpp_flags & IBMF_CTX_RMPP_FLAGS_DYN_PYLD) {
msgimplp->im_rmpp_ctx.rmpp_num_pkts = 100;
} else {
msgimplp->im_rmpp_ctx.rmpp_num_pkts =
rmpp_ctx->rmpp_pyld_len / cl_data_sz;
if ((rmpp_ctx->rmpp_pyld_len % cl_data_sz) != 0)
msgimplp->im_rmpp_ctx.rmpp_num_pkts++;
}
if ((rmpp_hdr->rmpp_flags & IBMF_RMPP_FLAGS_LAST_PKT) == 0) {
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main(): %s\n",
tnf_string, msg,
"First pkt recvd; setting trans timer: ",
tnf_opaque, msg, msgimplp);
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main(): setting trans"
" timer %p %d\n", tnf_opaque, msg, msgimplp,
tnf_opaque, timeout_id, msgimplp->im_rp_timeout_id);
ibmf_i_set_timer(ibmf_i_recv_timeout, msgimplp,
IBMF_TRANS_TIMER);
}
}
offset = sizeof (ib_mad_hdr_t) + cl_hdr_off + cl_hdr_sz;
if (rmpp_hdr->rmpp_flags & IBMF_RMPP_FLAGS_LAST_PKT)
data_sz = b2h32(rmpp_hdr->rmpp_pyldlen_nwl) - cl_hdr_sz;
else
data_sz = rmpp_ctx->rmpp_pkt_data_sz;
if (((data_sz + rmpp_ctx->rmpp_data_offset) >=
rmpp_ctx->rmpp_pyld_len) &&
((rmpp_ctx->rmpp_flags & IBMF_CTX_RMPP_FLAGS_DYN_PYLD) == 0)) {
if ((rmpp_hdr->rmpp_flags & IBMF_RMPP_FLAGS_LAST_PKT) == 0) {
status = ibmf_i_send_rmpp(msgimplp,
IBMF_RMPP_TYPE_ABORT, IBMF_RMPP_STATUS_ILPL,
0, 0, IBMF_NO_BLOCK);
if (status != IBMF_SUCCESS) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_i_rmpp_recvr_flow_main,
IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main(): %s\n",
tnf_string, msg, "RMPP ABORT send failed");
msgimplp->im_trans_state_flags |=
IBMF_TRANS_STATE_FLAG_SEND_DONE;
}
mutex_enter(&clientp->ic_kstat_mutex);
IBMF_ADD32_KSTATS(clientp, rmpp_errors, 1);
mutex_exit(&clientp->ic_kstat_mutex);
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main(): %s\n",
tnf_string, msg,
"Inconsistent last and payload length detected,"
" sending ABORT ILPL, unsetting trans timer");
rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
ibmf_i_unset_timer(msgimplp, IBMF_TRANS_TIMER);
ibmf_i_set_timer(ibmf_i_err_terminate_timeout,
msgimplp, IBMF_RESP_TIMER);
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_recvr_flow_main_end, IBMF_TNF_TRACE,
"", "ibmf_i_rmpp_recvr_flow_main() exit\n");
return;
}
} else if (((data_sz + rmpp_ctx->rmpp_data_offset) >=
rmpp_ctx->rmpp_pyld_len) &&
((rmpp_ctx->rmpp_flags & IBMF_CTX_RMPP_FLAGS_DYN_PYLD) != 0) &&
((rmpp_hdr->rmpp_flags & IBMF_RMPP_FLAGS_LAST_PKT) == 0)) {
ib_mad_hdr_t *old_buf;
size_t prev_pyld_len;
old_buf = msgimplp->im_msgbufs_recv.im_bufs_mad_hdr;
prev_pyld_len = rmpp_ctx->rmpp_pyld_len;
rmpp_ctx->rmpp_pyld_len +=
IBMF_BUF_PKTS * rmpp_ctx->rmpp_pkt_data_sz;
msgimplp->im_msgbufs_recv.im_bufs_cl_data_len =
rmpp_ctx->rmpp_pyld_len;
msgimplp->im_msgbufs_recv.im_bufs_mad_hdr =
(ib_mad_hdr_t *)kmem_zalloc(sizeof (ib_mad_hdr_t) +
cl_hdr_off + cl_hdr_sz + rmpp_ctx->rmpp_pyld_len,
KM_NOSLEEP);
if (msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL) {
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main(): %s, allocsz = %d\n",
tnf_string, msg,
"mem allocation failure (unknown rmpp payload)",
tnf_uint, alloc_size,
sizeof (ib_mad_hdr_t) + cl_hdr_off + cl_hdr_sz +
rmpp_ctx->rmpp_pyld_len);
ibmf_i_terminate_transaction(
msgimplp->im_client, msgimplp,
IBMF_NO_MEMORY);
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_recvr_flow_main_end, IBMF_TNF_TRACE,
"", "ibmf_i_rmpp_recvr_flow_main() exit\n");
return;
}
mutex_enter(&clientp->ic_kstat_mutex);
IBMF_ADD32_KSTATS(clientp, recv_bufs_alloced, 1);
mutex_exit(&clientp->ic_kstat_mutex);
msgbufp = (uchar_t *)msgimplp->im_msgbufs_recv.im_bufs_mad_hdr;
bcopy((const void *)old_buf, (void *)msgbufp,
sizeof (ib_mad_hdr_t) + cl_hdr_off + cl_hdr_sz +
prev_pyld_len);
kmem_free(old_buf, sizeof (ib_mad_hdr_t) + cl_hdr_off +
cl_hdr_sz + prev_pyld_len);
}
if (rmpp_ctx->rmpp_data_offset + data_sz >
rmpp_ctx->rmpp_pyld_len) {
data_sz = rmpp_ctx->rmpp_pyld_len -
rmpp_ctx->rmpp_data_offset;
}
datap = (uchar_t *)msgimplp->im_msgbufs_recv.im_bufs_cl_data;
bcopy((void *)&mad[offset],
(void *)(datap + rmpp_ctx->rmpp_data_offset), data_sz);
rmpp_ctx->rmpp_data_offset += data_sz;
rmpp_ctx->rmpp_es++;
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_rmpp_recvr_flow_main,
IBMF_TNF_TRACE, "", "ibmf_i_rmpp_recvr_flow_main(): es = %d\n",
tnf_uint, es, rmpp_ctx->rmpp_es);
if (rmpp_hdr->rmpp_flags & IBMF_RMPP_FLAGS_LAST_PKT) {
if ((rmpp_ctx->rmpp_flags & IBMF_CTX_RMPP_FLAGS_DYN_PYLD) !=
0) {
ib_mad_hdr_t *old_buf;
size_t prev_pyld_len;
rmpp_ctx->rmpp_flags &= ~IBMF_CTX_RMPP_FLAGS_DYN_PYLD;
old_buf = msgimplp->im_msgbufs_recv.im_bufs_mad_hdr;
prev_pyld_len = rmpp_ctx->rmpp_pyld_len;
rmpp_ctx->rmpp_pyld_len = rmpp_ctx->rmpp_data_offset;
msgimplp->im_msgbufs_recv.im_bufs_cl_data_len =
rmpp_ctx->rmpp_pyld_len;
msgimplp->im_msgbufs_recv.im_bufs_mad_hdr =
(ib_mad_hdr_t *)kmem_zalloc(sizeof (ib_mad_hdr_t) +
cl_hdr_off + cl_hdr_sz + rmpp_ctx->rmpp_pyld_len,
KM_NOSLEEP);
if (msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_recvr_flow_main,
IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main(): %s\n",
tnf_string, msg,
"mem allocation failure (final payload)");
ibmf_i_terminate_transaction(
msgimplp->im_client, msgimplp,
IBMF_NO_MEMORY);
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_recvr_flow_main_end,
IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main() exit\n");
return;
}
mutex_enter(&clientp->ic_kstat_mutex);
IBMF_ADD32_KSTATS(clientp, recv_bufs_alloced, 1);
mutex_exit(&clientp->ic_kstat_mutex);
msgbufp = (uchar_t *)
msgimplp->im_msgbufs_recv.im_bufs_mad_hdr;
bcopy((const void *)old_buf, (void *)msgbufp,
sizeof (ib_mad_hdr_t) + cl_hdr_off + cl_hdr_sz +
rmpp_ctx->rmpp_pyld_len);
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);
kmem_free(old_buf, sizeof (ib_mad_hdr_t) + cl_hdr_off +
cl_hdr_sz + prev_pyld_len);
}
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main(): %s, msgp = 0x%p\n",
tnf_string, msg,
"Last pkt rcvd; state to recv_term, sending ack",
tnf_opaque, msgp, msgimplp);
rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_RECEVR_TERMINATE;
status = ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ACK,
IBMF_RMPP_STATUS_NORMAL, rmpp_ctx->rmpp_es - 1,
rmpp_ctx->rmpp_es - 1 + IBMF_RMPP_DEFAULT_WIN_SZ,
IBMF_NO_BLOCK);
if (status != IBMF_SUCCESS) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main(): %s\n",
tnf_string, msg, "RMPP ACK send failed");
msgimplp->im_trans_state_flags |=
IBMF_TRANS_STATE_FLAG_SEND_DONE;
}
if ((rmpp_hdr->rmpp_flags & IBMF_RMPP_FLAGS_FIRST_PKT) == 0) {
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main(): %s, msgp = 0x%p\n",
tnf_string, msg, "Last, but not first segment",
tnf_opaque, msgp, msgimplp);
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main(): unsetting timer "
"%p %d\n", tnf_opaque, msgp, msgimplp,
tnf_opaque, timeout_id, msgimplp->im_rp_timeout_id);
ibmf_i_unset_timer(msgimplp, IBMF_TRANS_TIMER);
}
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main(): %s, msgp = 0x%p\n",
tnf_string, msg,
"Last pkt rcvd; setting resp timer",
tnf_opaque, msgp, msgimplp);
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main(): last packet, "
" returning data to client for message %p\n",
tnf_opaque, msgp, msgimplp);
ibmf_i_terminate_transaction(clientp, msgimplp, IBMF_SUCCESS);
msgimplp->im_flags |= IBMF_MSG_FLAGS_SET_TERMINATION;
return;
}
if (b2h32(rmpp_hdr->rmpp_segnum) == rmpp_ctx->rmpp_wl) {
IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main(): %s, msgp = 0x%p"
"segnum = %d, wl = %d\n", tnf_string, msg,
"Last packet in window received", tnf_opaque, msgimplp,
msgimplp, tnf_opaque, seg, b2h32(rmpp_hdr->rmpp_segnum),
tnf_opaque, wl, rmpp_ctx->rmpp_wl);
(void) ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ACK,
IBMF_RMPP_STATUS_NORMAL,
rmpp_ctx->rmpp_es - 1,
rmpp_ctx->rmpp_es - 1 +
IBMF_RMPP_DEFAULT_WIN_SZ, IBMF_NO_BLOCK);
rmpp_ctx->rmpp_wl += IBMF_RMPP_DEFAULT_WIN_SZ;
} else {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main(): %s\n",
tnf_string, msg, "Packet in window received");
}
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_recvr_flow_main_end, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_flow_main() exit\n");
}
static void
ibmf_i_rmpp_recvr_active_flow(ibmf_client_t *clientp, ibmf_qp_handle_t qp_hdl,
ibmf_msg_impl_t *msgimplp, uchar_t *mad)
{
ibmf_rmpp_ctx_t *rmpp_ctx = &msgimplp->im_rmpp_ctx;
ibmf_rmpp_hdr_t *rmpp_hdr;
uint32_t abort_status;
int status;
IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_recvr_active_flow_start, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_active_flow(): clientp = 0x%p, qp_hdl = 0x%p, "
"msgp = 0x%p, madp = 0x%p\n", tnf_opaque, clientp, clientp,
tnf_opaque, qp_hdl, qp_hdl, tnf_opaque, msg, msgimplp,
tnf_opaque, mad, mad);
rmpp_hdr = (ibmf_rmpp_hdr_t *)(mad + sizeof (ib_mad_hdr_t));
if (rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_ACK) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_recvr_active_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_active_flow(): %s\n", tnf_string, msg,
"ACK packet received, discarding packet");
if (rmpp_ctx->rmpp_es == 1) {
ibmf_i_set_timer(ibmf_i_send_timeout, msgimplp,
IBMF_RESP_TIMER);
}
return;
}
if (rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_DATA) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_recvr_active_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_active_flow(): %s\n", tnf_string, msg,
"DATA packet received, processing packet");
ibmf_i_rmpp_recvr_flow_main(clientp, qp_hdl, msgimplp, mad);
} else if ((rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_STOP) ||
(rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_ABORT)) {
abort_status = rmpp_hdr->rmpp_status;
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_i_rmpp_recvr_active_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_active_flow(): %s, status = %d\n",
tnf_string, msg,
"STOP/ABORT packet received, terminating transaction",
tnf_uint, abort_status, abort_status);
rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
msgimplp->im_trans_state_flags |=
IBMF_TRANS_STATE_FLAG_SEND_DONE;
ibmf_i_unset_timer(msgimplp, IBMF_TRANS_TIMER);
ibmf_i_set_timer(ibmf_i_err_terminate_timeout,
msgimplp, IBMF_RESP_TIMER);
} else {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_i_rmpp_recvr_active_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_active_flow(): %s\n", tnf_string, msg,
"Unrecognized packet received, terminating transaction");
status = ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ABORT,
IBMF_RMPP_STATUS_BADT, 0, 0, IBMF_NO_BLOCK);
if (status != IBMF_SUCCESS) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_i_rmpp_recvr_active_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_active_flow(): %s\n",
tnf_string, msg, "RMPP ABORT send failed");
msgimplp->im_trans_state_flags |=
IBMF_TRANS_STATE_FLAG_SEND_DONE;
}
rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
mutex_enter(&clientp->ic_kstat_mutex);
IBMF_ADD32_KSTATS(clientp, rmpp_errors, 1);
mutex_exit(&clientp->ic_kstat_mutex);
ibmf_i_unset_timer(msgimplp, IBMF_TRANS_TIMER);
ibmf_i_set_timer(ibmf_i_err_terminate_timeout,
msgimplp, IBMF_RESP_TIMER);
}
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_recvr_active_flow_end, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_active_flow() exit\n");
}
static void
ibmf_i_rmpp_recvr_term_flow(ibmf_client_t *clientp, ibmf_qp_handle_t qp_hdl,
ibmf_msg_impl_t *msgimplp, uchar_t *mad)
{
ibmf_rmpp_ctx_t *rmpp_ctx = &msgimplp->im_rmpp_ctx;
ibmf_rmpp_hdr_t *rmpp_hdr;
int status;
IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_recvr_term_flow_start, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_term_flow(): clientp = 0x%p, qp_hdl = 0x%p, "
"msgp = 0x%p, madp = 0x%p\n", tnf_opaque, clientp, clientp,
tnf_opaque, qp_hdl, qp_hdl, tnf_opaque, msg, msgimplp,
tnf_opaque, mad, mad);
rmpp_hdr = (ibmf_rmpp_hdr_t *)(mad + sizeof (ib_mad_hdr_t));
if (rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_DATA) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_recvr_term_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_term_flow(): %s\n", tnf_string, msg,
"Data packet received, resending ACK");
(void) ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ACK,
IBMF_RMPP_STATUS_NORMAL, rmpp_ctx->rmpp_es - 1,
rmpp_ctx->rmpp_es - 1 + IBMF_RMPP_DEFAULT_WIN_SZ,
IBMF_NO_BLOCK);
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_recvr_term_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_term_flow(): setting resp timer %d %p\n",
tnf_opaque, msgimplp, msgimplp, tnf_opaque,
timeout_id, msgimplp->im_rp_timeout_id);
ibmf_i_set_timer(ibmf_i_recv_timeout, msgimplp,
IBMF_RESP_TIMER);
} else if (rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_ACK) {
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_recvr_term_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_term_flow(): %s, msgp = 0x%p\n",
tnf_string, msg, "ACK packet received",
tnf_opaque, msgimplp, msgimplp);
if (rmpp_ctx->rmpp_is_ds) {
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_rmpp_recvr_term_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_term_flow(): %s, msgp = 0x%p\n",
tnf_string, msg,
"Received final ack for double-sided trans",
tnf_opaque, msgimplp, msgimplp);
rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_DONE;
ibmf_i_terminate_transaction(clientp, msgimplp,
IBMF_SUCCESS);
} else {
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_i_rmpp_recvr_term_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_term_flow(): %s, msgp = 0x%p\n",
tnf_string, msg, "Received ACK while in recv_term "
"state for single sided trans",
tnf_opaque, msgimplp, msgimplp);
(void) ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ABORT,
IBMF_RMPP_STATUS_BADT, 0, 0, IBMF_NO_BLOCK);
rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
ibmf_i_unset_timer(msgimplp, IBMF_TRANS_TIMER);
ibmf_i_set_timer(ibmf_i_err_terminate_timeout,
msgimplp, IBMF_RESP_TIMER);
}
} else {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_i_rmpp_recvr_term_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_term_flow(): %s\n", tnf_string, msg,
"Unexpected packet received, sending ABORT BADT");
status = ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ABORT,
IBMF_RMPP_STATUS_BADT, 0, 0, IBMF_NO_BLOCK);
if (status != IBMF_SUCCESS) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_i_rmpp_recvr_term_flow, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_term_flow(): %s\n",
tnf_string, msg, "RMPP ABORT send failed");
msgimplp->im_trans_state_flags |=
IBMF_TRANS_STATE_FLAG_SEND_DONE;
}
rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
mutex_enter(&clientp->ic_kstat_mutex);
IBMF_ADD32_KSTATS(clientp, rmpp_errors, 1);
mutex_exit(&clientp->ic_kstat_mutex);
ibmf_i_unset_timer(msgimplp, IBMF_TRANS_TIMER);
ibmf_i_set_timer(ibmf_i_err_terminate_timeout,
msgimplp, IBMF_RESP_TIMER);
}
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_rmpp_recvr_term_flow_end, IBMF_TNF_TRACE, "",
"ibmf_i_rmpp_recvr_term_flow() exit\n");
}
static boolean_t
ibmf_i_is_valid_rmpp_status(ibmf_rmpp_hdr_t *rmpp_hdr)
{
boolean_t found = B_TRUE;
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_is_valid_rmpp_status_start, IBMF_TNF_TRACE, "",
"ibmf_i_is_valid_rmpp_status(): rmpp_hdr = 0x%p\n",
tnf_opaque, rmpp_hdr, rmpp_hdr);
if (((rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_DATA) ||
(rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_ACK)) &&
(rmpp_hdr->rmpp_status != IBMF_RMPP_STATUS_NORMAL))
found = B_FALSE;
if ((rmpp_hdr->rmpp_status == IBMF_RMPP_STATUS_RESX) &&
(rmpp_hdr->rmpp_type != IBMF_RMPP_TYPE_STOP))
found = B_FALSE;
if (((rmpp_hdr->rmpp_status == IBMF_RMPP_STATUS_T2L) ||
(rmpp_hdr->rmpp_status == IBMF_RMPP_STATUS_ILPL) ||
(rmpp_hdr->rmpp_status == IBMF_RMPP_STATUS_IFSN) ||
(rmpp_hdr->rmpp_status == IBMF_RMPP_STATUS_BADT) ||
(rmpp_hdr->rmpp_status == IBMF_RMPP_STATUS_W2S) ||
(rmpp_hdr->rmpp_status == IBMF_RMPP_STATUS_S2B) ||
(rmpp_hdr->rmpp_status == IBMF_RMPP_STATUS_IS) ||
(rmpp_hdr->rmpp_status == IBMF_RMPP_STATUS_UNV) ||
(rmpp_hdr->rmpp_status == IBMF_RMPP_STATUS_TMR) ||
(rmpp_hdr->rmpp_status == IBMF_RMPP_STATUS_USP)) &&
(rmpp_hdr->rmpp_type != IBMF_RMPP_TYPE_ABORT))
found = B_FALSE;
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_is_valid_rmpp_status_end, IBMF_TNF_TRACE, "",
"ibmf_i_is_valid_rmpp_status_flow() exit\n");
return (found);
}
void
ibmf_i_handle_rmpp(ibmf_client_t *clientp, ibmf_qp_handle_t qp_hdl,
ibmf_msg_impl_t *msgimplp, uchar_t *madp)
{
ibmf_rmpp_ctx_t *rmpp_ctx = &msgimplp->im_rmpp_ctx;
ibmf_rmpp_hdr_t *rmpp_hdr;
int status;
IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_handle_rmpp_start, IBMF_TNF_TRACE, "",
"ibmf_i_handle_rmpp(): clientp = 0x%p, qp_hdl = 0x%p, "
"msgp = 0x%p, madp = 0x%p\n", tnf_opaque, clientp, clientp,
tnf_opaque, qp_hdl, qp_hdl, tnf_opaque, msg, msgimplp,
tnf_opaque, mad, madp);
ASSERT(MUTEX_HELD(&msgimplp->im_mutex));
rmpp_hdr = (ibmf_rmpp_hdr_t *)(madp + sizeof (ib_mad_hdr_t));
if (rmpp_hdr->rmpp_version != IBMF_RMPP_VERSION) {
if (msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL) {
status = ibmf_setup_recvbuf_on_error(msgimplp, madp);
if (status != IBMF_SUCCESS) {
IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L2,
ibmf_i_handle_rmpp_err, IBMF_TNF_ERROR, "",
"ibmf_i_handle_rmpp(): %s\n", tnf_string,
msg,
"ibmf_setup_recvbuf_on_error() failed");
return;
}
}
if (((msgimplp->im_flags & IBMF_MSG_FLAGS_RECV_RMPP) == 0) &&
(msgimplp->im_flags & IBMF_MSG_FLAGS_SEND_RMPP) == 0) {
if (msgimplp->im_trans_state_flags &
IBMF_TRANS_STATE_FLAG_SEND_DONE) {
ibmf_i_set_timer(ibmf_i_send_timeout, msgimplp,
IBMF_RESP_TIMER);
}
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_handle_rmpp, IBMF_TNF_TRACE, "",
"ibmf_i_handle_rmpp(): %s\n", tnf_string, msg,
"BAD version detected, dropping MAD");
return;
}
status = ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ABORT,
IBMF_RMPP_STATUS_UNV, 0, 0, IBMF_NO_BLOCK);
if (status != IBMF_SUCCESS) {
IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L2,
ibmf_i_handle_rmpp_err, IBMF_TNF_ERROR, "",
"ibmf_i_handle_rmpp(): %s\n", tnf_string, msg,
"RMPP ABORT send failed");
msgimplp->im_trans_state_flags |=
IBMF_TRANS_STATE_FLAG_SEND_DONE;
}
mutex_enter(&clientp->ic_kstat_mutex);
IBMF_ADD32_KSTATS(clientp, rmpp_errors, 1);
mutex_exit(&clientp->ic_kstat_mutex);
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_i_handle_rmpp, IBMF_TNF_TRACE, "",
"ibmf_i_handle_rmpp(): %s\n", tnf_string, msg,
"Unsupported RMPP version detected, sending ABORT UNV");
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_handle_rmpp_end, IBMF_TNF_TRACE, "",
"ibmf_i_handle_rmpp() exit\n");
rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
ibmf_i_unset_timer(msgimplp, IBMF_TRANS_TIMER);
ibmf_i_set_timer(ibmf_i_err_terminate_timeout,
msgimplp, IBMF_RESP_TIMER);
return;
}
if (ibmf_i_is_valid_rmpp_status(rmpp_hdr) != B_TRUE) {
if (msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL) {
status = ibmf_setup_recvbuf_on_error(msgimplp, madp);
if (status != IBMF_SUCCESS) {
IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L2,
ibmf_i_handle_rmpp_err, IBMF_TNF_ERROR, "",
"ibmf_i_handle_rmpp(): %s\n", tnf_string,
msg,
"ibmf_setup_recvbuf_on_error() failed");
return;
}
}
if (((msgimplp->im_flags & IBMF_MSG_FLAGS_RECV_RMPP) == 0) &&
(msgimplp->im_flags & IBMF_MSG_FLAGS_SEND_RMPP) == 0) {
if (msgimplp->im_trans_state_flags &
IBMF_TRANS_STATE_FLAG_SEND_DONE) {
ibmf_i_set_timer(ibmf_i_send_timeout, msgimplp,
IBMF_RESP_TIMER);
}
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_handle_rmpp, IBMF_TNF_TRACE, "",
"ibmf_i_handle_rmpp(): %s\n", tnf_string, msg,
"Invalid RMPP status detected, dropping MAD");
return;
}
status = ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ABORT,
IBMF_RMPP_STATUS_IS, 0, 0, IBMF_NO_BLOCK);
if (status != IBMF_SUCCESS) {
IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L2,
ibmf_i_handle_rmpp_err, IBMF_TNF_ERROR, "",
"ibmf_i_handle_rmpp(): %s\n", tnf_string, msg,
"RMPP ABORT send failed");
msgimplp->im_trans_state_flags |=
IBMF_TRANS_STATE_FLAG_SEND_DONE;
}
mutex_enter(&clientp->ic_kstat_mutex);
IBMF_ADD32_KSTATS(clientp, rmpp_errors, 1);
mutex_exit(&clientp->ic_kstat_mutex);
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_i_handle_rmpp, IBMF_TNF_TRACE, "",
"ibmf_i_handle_rmpp(): %s\n", tnf_string, msg,
"Invalid RMPP status detected, sending ABORT IS");
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_handle_rmpp_end, IBMF_TNF_TRACE, "",
"ibmf_i_handle_rmpp() exit\n");
rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
ibmf_i_unset_timer(msgimplp, IBMF_TRANS_TIMER);
ibmf_i_set_timer(ibmf_i_err_terminate_timeout,
msgimplp, IBMF_RESP_TIMER);
return;
}
switch (rmpp_ctx->rmpp_state) {
case IBMF_RMPP_STATE_SENDER_ACTIVE :
ibmf_i_rmpp_sender_active_flow(clientp, qp_hdl, msgimplp, madp);
break;
case IBMF_RMPP_STATE_SENDER_SWITCH :
ibmf_i_rmpp_sender_switch_flow(clientp, qp_hdl, msgimplp, madp);
break;
case IBMF_RMPP_STATE_RECEVR_ACTIVE :
ibmf_i_rmpp_recvr_active_flow(clientp, qp_hdl, msgimplp, madp);
break;
case IBMF_RMPP_STATE_RECEVR_TERMINATE :
ibmf_i_rmpp_recvr_term_flow(clientp, qp_hdl, msgimplp, madp);
break;
default:
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_i_handle_rmpp, IBMF_TNF_TRACE, "",
"ibmf_i_handle_rmpp(): %s, rmpp_state = 0x%x\n",
tnf_string, msg, "Dropping packet",
tnf_opaque, rmpp_state, rmpp_ctx->rmpp_state);
if (rmpp_ctx->rmpp_state == IBMF_RMPP_STATE_ABORT) {
ibmf_i_set_timer(ibmf_i_err_terminate_timeout, msgimplp,
IBMF_RESP_TIMER);
return;
}
if (((msgimplp->im_flags & IBMF_MSG_FLAGS_RECV_RMPP) == 0) &&
(msgimplp->im_flags & IBMF_MSG_FLAGS_SEND_RMPP) == 0) {
if (msgimplp->im_trans_state_flags &
IBMF_TRANS_STATE_FLAG_SEND_DONE) {
ibmf_i_set_timer(ibmf_i_send_timeout, msgimplp,
IBMF_RESP_TIMER);
}
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_i_handle_rmpp, IBMF_TNF_TRACE, "",
"ibmf_i_handle_rmpp(): %s\n", tnf_string, msg,
"BAD 1st RMPP packet, dropping MAD");
return;
}
}
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_handle_rmpp_end, IBMF_TNF_TRACE, "",
"ibmf_i_handle_rmpp() exit\n");
}
int
ibmf_i_send_rmpp(ibmf_msg_impl_t *msgimplp, uint8_t rmpp_type,
uint8_t rmpp_status, uint32_t segno, uint32_t nwl, int block)
{
ibmf_rmpp_ctx_t *rmpp_ctx = &msgimplp->im_rmpp_ctx;
int status;
IBMF_TRACE_5(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_send_rmpp_start,
IBMF_TNF_TRACE, "",
"ibmf_i_send_rmpp(): msgp = 0x%p, rmpp_type = 0x%x, "
"rmpp_status = %d, segno = %d, nwl = %d\n",
tnf_opaque, msg, msgimplp,
tnf_uint, rmpp_type, rmpp_type,
tnf_uint, rmpp_status, rmpp_status,
tnf_uint, segno, segno,
tnf_uint, nwl, nwl);
IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_send_rmpp,
IBMF_TNF_TRACE, "", "ibmf_i_send_rmpp(): msgp = 0x%p, "
"next_seg = 0x%x, num_pkts = %d\n",
tnf_opaque, msg, msgimplp,
tnf_uint, next_seg, msgimplp->im_rmpp_ctx.rmpp_ns,
tnf_uint, num_pkts, msgimplp->im_rmpp_ctx.rmpp_num_pkts);
ASSERT(MUTEX_HELD(&msgimplp->im_mutex));
rmpp_ctx->rmpp_type = rmpp_type;
rmpp_ctx->rmpp_status = rmpp_status;
rmpp_ctx->rmpp_word3 = segno;
rmpp_ctx->rmpp_word4 = nwl;
status = ibmf_i_send_pkt(msgimplp->im_client, msgimplp->im_qp_hdl,
msgimplp, block);
if (status != IBMF_SUCCESS) {
IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_i_send_rmpp_err, IBMF_TNF_ERROR, "",
"ibmf_i_send_rmpp(): %s, status = %d\n", tnf_string, msg,
"unable to send packet", tnf_uint, status, status);
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_send_rmpp_end,
IBMF_TNF_TRACE, "", "ibmf_i_send_rmpp() exit\n");
return (status);
}
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_send_rmpp_end,
IBMF_TNF_TRACE, "", "ibmf_i_send_rmpp() exit\n");
return (IBMF_SUCCESS);
}
void
ibmf_i_send_rmpp_window(ibmf_msg_impl_t *msgimplp, int block)
{
ibmf_rmpp_ctx_t *rmpp_ctx = &msgimplp->im_rmpp_ctx;
int status, i, numpkts = rmpp_ctx->rmpp_wl - rmpp_ctx->rmpp_ns + 1;
uint32_t payload_length, cl_hdr_sz, cl_hdr_off;
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_send_rmpp_window_start,
IBMF_TNF_TRACE, "", "ibmf_i_send_rmpp_window(): msgp = 0x%p\n",
tnf_opaque, msg, msgimplp);
IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_send_rmpp_window,
IBMF_TNF_TRACE, "", "ibmf_i_handle_rmpp(): wl = %d "
"ns = %d, num_pkts = %d\n", tnf_uint, wl, rmpp_ctx->rmpp_wl,
tnf_uint, ns, rmpp_ctx->rmpp_ns, tnf_uint, num_pkts,
rmpp_ctx->rmpp_num_pkts);
ASSERT(MUTEX_HELD(&msgimplp->im_mutex));
ibmf_i_mgt_class_to_hdr_sz_off(
msgimplp->im_msgbufs_send.im_bufs_mad_hdr->MgmtClass,
&cl_hdr_sz, &cl_hdr_off);
for (i = 1; i <= numpkts; i++) {
if (rmpp_ctx->rmpp_ns == 1)
payload_length = rmpp_ctx->rmpp_pyld_len +
(rmpp_ctx->rmpp_num_pkts * cl_hdr_sz);
else if (rmpp_ctx->rmpp_ns == rmpp_ctx->rmpp_num_pkts)
payload_length = rmpp_ctx->rmpp_last_pkt_sz + cl_hdr_sz;
else
payload_length = rmpp_ctx->rmpp_pkt_data_sz;
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_send_rmpp_window,
IBMF_TNF_TRACE, "", "ibmf_i_handle_rmpp(): ns = %d, "
"pl = %d\n", tnf_uint, ns, rmpp_ctx->rmpp_ns,
tnf_uint, pl, payload_length);
status = ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_DATA,
IBMF_RMPP_STATUS_NORMAL, rmpp_ctx->rmpp_ns, payload_length,
block);
if (status != IBMF_SUCCESS) {
IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_i_send_rmpp_window_err, IBMF_TNF_ERROR, "",
"ibmf_i_send_rmpp_window(): %s\n", tnf_string, msg,
"Send rmpp window failed");
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_i_send_rmpp_window_end, IBMF_TNF_TRACE, "",
"ibmf_i_send_rmpp_window() exit\n");
return;
}
rmpp_ctx->rmpp_ns++;
rmpp_ctx->rmpp_data_offset += rmpp_ctx->rmpp_pkt_data_sz;
}
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_send_rmpp_window,
IBMF_TNF_TRACE, "", "ibmf_i_handle_rmpp(): setting timer %p %d\n",
tnf_opaque, msgimplp, msgimplp, tnf_opaque, timeout_id,
msgimplp->im_rp_timeout_id);
ibmf_i_set_timer(ibmf_i_send_timeout, msgimplp, IBMF_RESP_TIMER);
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_send_rmpp_window_end,
IBMF_TNF_TRACE, "", "ibmf_i_send_rmpp_window() exit\n");
}
int
ibmf_i_send_rmpp_pkts(ibmf_client_t *clientp, ibmf_qp_handle_t ibmf_qp_handle,
ibmf_msg_impl_t *msgimplp, boolean_t isDS, int block)
{
ibmf_rmpp_ctx_t *rmpp_ctx = &msgimplp->im_rmpp_ctx;
size_t buf_sz = msgimplp->im_msgbufs_send.im_bufs_cl_data_len;
uint32_t num_pkts, resid;
uint32_t cl_hdr_sz, cl_data_sz, cl_hdr_off;
IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_send_rmpp_pkts_start,
IBMF_TNF_TRACE, "", "ibmf_i_send_rmpp_pkts(): clientp = 0x%p, "
"qphdl = 0x%p, msgp = 0x%p, block = %d\n",
tnf_opaque, clientp, clientp, tnf_opaque, qphdl, ibmf_qp_handle,
tnf_opaque, msg, msgimplp, tnf_uint, block, block);
ASSERT(MUTEX_HELD(&msgimplp->im_mutex));
ibmf_i_mgt_class_to_hdr_sz_off(
msgimplp->im_msgbufs_send.im_bufs_mad_hdr->MgmtClass,
&cl_hdr_sz, &cl_hdr_off);
cl_data_sz = MAD_SIZE_IN_BYTES - sizeof (ib_mad_hdr_t) - cl_hdr_off -
cl_hdr_sz;
if ((resid = (buf_sz % cl_data_sz)) != 0)
num_pkts = (buf_sz / cl_data_sz) + 1;
else {
if (buf_sz > 0)
num_pkts = buf_sz / cl_data_sz;
else
num_pkts = 1;
}
rmpp_ctx->rmpp_wf = 1;
rmpp_ctx->rmpp_wl = 1;
rmpp_ctx->rmpp_ns = 1;
rmpp_ctx->rmpp_is_ds = isDS;
rmpp_ctx->rmpp_pyld_len = buf_sz;
rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_SENDER_ACTIVE;
rmpp_ctx->rmpp_type = IBMF_RMPP_TYPE_DATA;
rmpp_ctx->rmpp_respt = IBMF_RMPP_TERM_RRESPT;
rmpp_ctx->rmpp_status = IBMF_RMPP_STATUS_NORMAL;
rmpp_ctx->rmpp_num_pkts = num_pkts;
rmpp_ctx->rmpp_pkt_data_sz =
(buf_sz < cl_data_sz) ? buf_sz : cl_data_sz;
rmpp_ctx->rmpp_last_pkt_sz =
(resid == 0) ? ((buf_sz == 0) ? 0 : cl_data_sz) : resid;
rmpp_ctx->rmpp_data_offset = 0;
ibmf_i_send_rmpp_window(msgimplp, block);
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_send_rmpp_pkts_end,
IBMF_TNF_TRACE, "", "ibmf_i_send_rmpp_pkts() exit\n");
return (IBMF_SUCCESS);
}