xref: /illumos-gate/usr/src/uts/common/io/ib/mgt/ibmf/ibmf_rmpp.c (revision a4955f4fa65e38d70c07d38e657a9aff43fa155f)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * This file contains the routines to implement the RMPP protocol.
29  */
30 
31 #include <sys/ib/mgt/ibmf/ibmf_impl.h>
32 
33 extern ibmf_state_t *ibmf_statep;
34 extern int ibmf_trace_level;
35 
36 #define	IBMF_BUF_PKTS	10
37 
38 static void ibmf_i_rmpp_sender_active_flow(ibmf_client_t *clientp,
39     ibmf_qp_handle_t qp_hdl, ibmf_msg_impl_t *msgimplp, uchar_t *mad);
40 static void ibmf_i_rmpp_sender_switch_flow(ibmf_client_t *clientp,
41     ibmf_qp_handle_t qp_hdl, ibmf_msg_impl_t *msgimplp, uchar_t *mad);
42 static void ibmf_i_rmpp_recvr_flow_main(ibmf_client_t *clientp,
43     ibmf_qp_handle_t qp_hdl, ibmf_msg_impl_t *msgimplp, uchar_t *mad);
44 static void ibmf_i_rmpp_recvr_active_flow(ibmf_client_t *clientp,
45     ibmf_qp_handle_t qp_hdl, ibmf_msg_impl_t *msgimplp, uchar_t *mad);
46 static void ibmf_i_rmpp_recvr_term_flow(ibmf_client_t *clientp,
47     ibmf_qp_handle_t qp_hdl, ibmf_msg_impl_t *msgimplp, uchar_t *mad);
48 static boolean_t ibmf_i_is_valid_rmpp_status(ibmf_rmpp_hdr_t *rmpp_hdr);
49 
50 /*
51  * ibmf_i_is_rmpp():
52  *	Check if the client and QP context supports RMPP transfers
53  */
54 boolean_t
55 ibmf_i_is_rmpp(ibmf_client_t *clientp, ibmf_qp_handle_t ibmf_qp_handle)
56 {
57 	ibmf_alt_qp_t	*qpp = (ibmf_alt_qp_t *)ibmf_qp_handle;
58 	boolean_t	is_rmpp;
59 
60 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_is_rmpp_start,
61 	    IBMF_TNF_TRACE, "", "ibmf_i_is_rmpp(): clientp = %p, "
62 	    "ibmf_qp_handle = 0x%p\n", tnf_opaque, clientp, clientp,
63 	    tnf_opaque, ibmf_qp_handle, ibmf_qp_handle);
64 
65 	if ((clientp->ic_reg_flags & IBMF_REG_FLAG_RMPP) == 0) {
66 		is_rmpp = B_FALSE;
67 	} else if ((ibmf_qp_handle != IBMF_QP_HANDLE_DEFAULT) &&
68 	    (qpp->isq_supports_rmpp == B_FALSE)) {
69 		is_rmpp = B_FALSE;
70 	} else {
71 		is_rmpp = B_TRUE;
72 	}
73 
74 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_is_rmpp_end,
75 	    IBMF_TNF_TRACE, "", "ibmf_i_is_rmpp() exit, is_rmpp = %d\n",
76 	    tnf_uint, is_rmpp, is_rmpp);
77 
78 	return (is_rmpp);
79 }
80 
81 /*
82  * ibmf_i_rmpp_sender_active_flow():
83  *	Perform RMPP processing for the sender side transaction.
84  *	Refer to figure 178 "RMPP Sender Main Flow Diagram" of
85  *	the InfiniBand Architecture Specification Volume 1, Release 1.1
86  */
87 static void
88 ibmf_i_rmpp_sender_active_flow(ibmf_client_t *clientp, ibmf_qp_handle_t qp_hdl,
89     ibmf_msg_impl_t *msgimplp, uchar_t *mad)
90 {
91 	ibmf_rmpp_ctx_t	*rmpp_ctx = &msgimplp->im_rmpp_ctx;
92 	ibmf_rmpp_hdr_t *rmpp_hdr;
93 	uint32_t	abort_status;
94 	int		status;
95 
96 	IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4,
97 	    ibmf_i_rmpp_sender_active_flow_start, IBMF_TNF_TRACE, "",
98 	    "ibmf_i_rmpp_sender_active_flow(): clientp = 0x%p, qp_hdl = 0x%p, "
99 	    "msgp = 0x%p, madp = 0x%p\n", tnf_opaque, clientp, clientp,
100 	    tnf_opaque, qp_hdl, qp_hdl, tnf_opaque, msg, msgimplp,
101 	    tnf_opaque, mad, mad);
102 
103 	/*
104 	 * RMPP header is located just after the MAD header for SA MADs
105 	 * If this changes for Vendor MADs, we will need some way for
106 	 * the client to specify the byte offset of the RMPP header
107 	 * within the MAD.
108 	 */
109 	rmpp_hdr = (ibmf_rmpp_hdr_t *)(mad + sizeof (ib_mad_hdr_t));
110 
111 	if (rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_DATA) {
112 
113 		IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
114 		    ibmf_i_rmpp_sender_active_flow, IBMF_TNF_TRACE, "",
115 		    "ibmf_i_rmpp_sender_active_flow(): %s\n", tnf_string, msg,
116 		    "Data packet received, discarding it");
117 
118 		/*
119 		 * According to the IB spec, we discard the packet and resend
120 		 * packets next_seg->window_last.  However, next_seg is equal to
121 		 * window_last so send_rmpp_window() will just reset the timer.
122 		 */
123 		ibmf_i_send_rmpp_window(msgimplp, IBMF_NO_BLOCK);
124 
125 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
126 		    ibmf_i_rmpp_sender_active_flow_end, IBMF_TNF_TRACE, "",
127 		    "ibmf_i_rmpp_sender_active_flow() exit\n");
128 
129 		return;
130 	}
131 
132 	if (rmpp_hdr->rmpp_type != IBMF_RMPP_TYPE_ACK) {
133 
134 		if ((rmpp_hdr->rmpp_type != IBMF_RMPP_TYPE_STOP) &&
135 		    (rmpp_hdr->rmpp_type != IBMF_RMPP_TYPE_ABORT)) {
136 
137 			IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
138 			    ibmf_i_rmpp_sender_active_flow, IBMF_TNF_TRACE, "",
139 			    "ibmf_i_rmpp_sender_active_flow(): %s\n",
140 			    tnf_string, msg,
141 			    "Unrecognized packet received, sending ABORT");
142 
143 			/* abort with status BadT */
144 			status = ibmf_i_send_rmpp(msgimplp,
145 			    IBMF_RMPP_TYPE_ABORT, IBMF_RMPP_STATUS_BADT,
146 			    0, 0, IBMF_NO_BLOCK);
147 			if (status != IBMF_SUCCESS) {
148 				IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
149 				    ibmf_i_rmpp_sender_active_flow,
150 				    IBMF_TNF_TRACE, "",
151 				    "ibmf_i_rmpp_sender_active_flow(): %s\n",
152 				    tnf_string, msg, "RMPP ABORT send failed");
153 				msgimplp->im_trans_state_flags |=
154 				    IBMF_TRANS_STATE_FLAG_SEND_DONE;
155 			}
156 
157 			mutex_enter(&clientp->ic_kstat_mutex);
158 			IBMF_ADD32_KSTATS(clientp, rmpp_errors, 1);
159 			mutex_exit(&clientp->ic_kstat_mutex);
160 
161 		} else {
162 
163 			abort_status = rmpp_hdr->rmpp_status;
164 
165 			IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L2,
166 			    ibmf_i_rmpp_sender_active_flow, IBMF_TNF_TRACE, "",
167 			    "ibmf_i_rmpp_sender_active_flow(): %s, "
168 			    "status = %d\n", tnf_string, msg,
169 			    "STOP or ABORT packet received, terminating",
170 			    tnf_uint, abort_status, abort_status);
171 		}
172 
173 		rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
174 		msgimplp->im_trans_state_flags |=
175 		    IBMF_TRANS_STATE_FLAG_SEND_DONE;
176 
177 		ibmf_i_set_timer(ibmf_i_err_terminate_timeout, msgimplp,
178 		    IBMF_RESP_TIMER);
179 
180 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
181 		    ibmf_i_rmpp_sender_active_flow_end, IBMF_TNF_TRACE, "",
182 		    "ibmf_i_rmpp_sender_active_flow() exit\n");
183 
184 		return;
185 	}
186 
187 	IBMF_TRACE_5(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_rmpp_sender_active_flow,
188 	    IBMF_TNF_TRACE, "", "ibmf_i_rmpp_sender_active_flow(): %s, "
189 	    "msgp = 0x%p, recvd seg = %d wl = %d wf = %d\n",
190 	    tnf_string, msg, "ACK packet received",
191 	    tnf_opaque, msgp, msgimplp, tnf_uint, recvd_seg,
192 	    b2h32(rmpp_hdr->rmpp_segnum), tnf_uint, wl, rmpp_ctx->rmpp_wl,
193 	    tnf_uint, wf, rmpp_ctx->rmpp_wf);
194 
195 
196 	/* only ACK packets get here */
197 	if (b2h32(rmpp_hdr->rmpp_segnum) > rmpp_ctx->rmpp_wl) {
198 
199 		/* abort with status S2B */
200 		status = ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ABORT,
201 		    IBMF_RMPP_STATUS_S2B, 0, 0, IBMF_NO_BLOCK);
202 		if (status != IBMF_SUCCESS) {
203 			IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
204 			    ibmf_i_rmpp_sender_active_flow, IBMF_TNF_TRACE, "",
205 			    "ibmf_i_rmpp_sender_active_flow(): %s\n",
206 			    tnf_string, msg, "RMPP ABORT send failed");
207 			msgimplp->im_trans_state_flags |=
208 			    IBMF_TRANS_STATE_FLAG_SEND_DONE;
209 		}
210 
211 		mutex_enter(&clientp->ic_kstat_mutex);
212 		IBMF_ADD32_KSTATS(clientp, rmpp_errors, 1);
213 		mutex_exit(&clientp->ic_kstat_mutex);
214 
215 		IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
216 		    ibmf_i_rmpp_sender_active_flow, IBMF_TNF_TRACE, "",
217 		    "ibmf_i_rmpp_sender_active_flow(): %s\n",
218 		    tnf_string, msg, "Segnum > WL");
219 
220 		rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
221 
222 		ibmf_i_set_timer(ibmf_i_err_terminate_timeout,
223 		    msgimplp, IBMF_RESP_TIMER);
224 
225 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
226 		    ibmf_i_rmpp_sender_active_flow_end, IBMF_TNF_TRACE, "",
227 		    "ibmf_i_rmpp_sender_active_flow() exit\n");
228 
229 		return;
230 	}
231 
232 	if (b2h32(rmpp_hdr->rmpp_segnum) < rmpp_ctx->rmpp_wf) {
233 
234 		IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
235 		    ibmf_i_rmpp_sender_active_flow, IBMF_TNF_TRACE, "",
236 		    "ibmf_i_rmpp_sender_active_flow(): %s\n",
237 		    tnf_string, msg, "Segnum < WF");
238 
239 		/* discard the packet by not processing it here */
240 
241 		/* send the window */
242 		ibmf_i_send_rmpp_window(msgimplp, IBMF_NO_BLOCK);
243 
244 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
245 		    ibmf_i_rmpp_sender_active_flow_end, IBMF_TNF_TRACE, "",
246 		    "ibmf_i_rmpp_sender_active_flow() exit\n");
247 
248 		return;
249 	}
250 
251 	/* only ACK packets with valid segnum get here */
252 	if (b2h32(rmpp_hdr->rmpp_pyldlen_nwl) < rmpp_ctx->rmpp_wl) {
253 
254 		IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
255 		    ibmf_i_rmpp_sender_active_flow, IBMF_TNF_TRACE, "",
256 		    "ibmf_i_rmpp_sender_active_flow(): %s\n",
257 		    tnf_string, msg, "NWL < WL");
258 
259 		/* abort with status W2S */
260 		status = ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ABORT,
261 		    IBMF_RMPP_STATUS_W2S, 0, 0, IBMF_NO_BLOCK);
262 		if (status != IBMF_SUCCESS) {
263 			IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
264 			    ibmf_i_rmpp_sender_active_flow, IBMF_TNF_TRACE, "",
265 			    "ibmf_i_rmpp_sender_active_flow(): %s\n",
266 			    tnf_string, msg, "RMPP ABORT send failed");
267 			msgimplp->im_trans_state_flags |=
268 			    IBMF_TRANS_STATE_FLAG_SEND_DONE;
269 		}
270 
271 		mutex_enter(&clientp->ic_kstat_mutex);
272 		IBMF_ADD32_KSTATS(clientp, rmpp_errors, 1);
273 		mutex_exit(&clientp->ic_kstat_mutex);
274 
275 		rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
276 
277 		ibmf_i_set_timer(ibmf_i_err_terminate_timeout,
278 		    msgimplp, IBMF_RESP_TIMER);
279 
280 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
281 		    ibmf_i_rmpp_sender_active_flow_end, IBMF_TNF_TRACE, "",
282 		    "ibmf_i_rmpp_sender_active_flow() exit\n");
283 
284 		return;
285 	}
286 
287 	/* is ACK of last packet */
288 
289 	if (b2h32(rmpp_hdr->rmpp_segnum) == rmpp_ctx->rmpp_num_pkts) {
290 
291 		IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3,
292 		    ibmf_i_rmpp_sender_active_flow, IBMF_TNF_TRACE, "",
293 		    "ibmf_i_rmpp_sender_active_flow(): %s, msgp = 0x%p, "
294 		    "double-sided = %d\n", tnf_string, msg, "Last packet",
295 		    tnf_opaque, msgimplp, msgimplp,
296 		    tnf_opaque, double_sided, rmpp_ctx->rmpp_is_ds);
297 
298 		if (rmpp_ctx->rmpp_is_ds) {
299 
300 			IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
301 			    ibmf_i_rmpp_sender_active_flow, IBMF_TNF_TRACE, "",
302 			    "ibmf_i_rmpp_sender_active_flow(): %s, "
303 			    "msgp = 0x%p\n", tnf_string, msg,
304 			    "Doublesided,sending ACK and switching to receiver",
305 			    tnf_opaque, msgimplp, msgimplp);
306 
307 			rmpp_ctx->rmpp_is_ds = B_FALSE;
308 			rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_SENDER_SWITCH;
309 			rmpp_ctx->rmpp_wf = 1;
310 			rmpp_ctx->rmpp_wl = 1;
311 			rmpp_ctx->rmpp_es = 1;
312 
313 			(void) ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ACK,
314 			    IBMF_RMPP_STATUS_NORMAL, 0, 1, IBMF_NO_BLOCK);
315 
316 			/* set the response timer */
317 			ibmf_i_set_timer(ibmf_i_send_timeout,
318 			    msgimplp, IBMF_RESP_TIMER);
319 
320 			/* proceed with sender switch to receiver */
321 			IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
322 			    ibmf_i_rmpp_sender_active_flow_end,
323 			    IBMF_TNF_TRACE, "",
324 			    "ibmf_i_rmpp_sender_active_flow() exit\n");
325 			return;
326 		}
327 
328 		/* successful termination */
329 		rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_DONE;
330 		ibmf_i_terminate_transaction(clientp, msgimplp, IBMF_SUCCESS);
331 
332 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
333 		    ibmf_i_rmpp_sender_active_flow_end, IBMF_TNF_TRACE, "",
334 		    "ibmf_i_rmpp_sender_active_flow() exit\n");
335 		return;
336 	}
337 
338 	/* update RMPP context and send the next window */
339 	rmpp_ctx->rmpp_wf = b2h32(rmpp_hdr->rmpp_segnum) + 1;
340 	rmpp_ctx->rmpp_ns = b2h32(rmpp_hdr->rmpp_segnum) + 1;
341 	rmpp_ctx->rmpp_wl =
342 	    (rmpp_ctx->rmpp_num_pkts < b2h32(rmpp_hdr->rmpp_pyldlen_nwl)) ?
343 	    rmpp_ctx->rmpp_num_pkts : b2h32(rmpp_hdr->rmpp_pyldlen_nwl);
344 
345 	IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_rmpp_sender_active_flow,
346 	    IBMF_TNF_TRACE, "", "ibmf_i_rmpp_sender_active_flow(): %s, "
347 	    "wf = %d, wl = %d, ns = %d\n",
348 	    tnf_string, msg, "sending next window",
349 	    tnf_uint, wf, rmpp_ctx->rmpp_wf, tnf_uint, wl, rmpp_ctx->rmpp_wl,
350 	    tnf_uint, ns, rmpp_ctx->rmpp_ns);
351 
352 	/* send the window */
353 	ibmf_i_send_rmpp_window(msgimplp, IBMF_NO_BLOCK);
354 
355 	/* carry on with the protocol */
356 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
357 	    ibmf_i_rmpp_sender_active_flow_end, IBMF_TNF_TRACE, "",
358 	    "ibmf_i_rmpp_sender_active_flow() exit\n");
359 }
360 
361 /*
362  * ibmf_i_rmpp_sender_switch_flow():
363  *	Perform sender to receiver flow processing switch.
364  *	Refer to figure 179 "RMPP Sender Direction Switch Flow Diagram" of
365  *	the InfiniBand Architecture Specification Volume 1, Release 1.1
366  */
367 static void
368 ibmf_i_rmpp_sender_switch_flow(ibmf_client_t *clientp, ibmf_qp_handle_t qp_hdl,
369     ibmf_msg_impl_t *msgimplp, uchar_t *mad)
370 {
371 	ibmf_rmpp_ctx_t	*rmpp_ctx = &msgimplp->im_rmpp_ctx;
372 	ibmf_rmpp_hdr_t *rmpp_hdr;
373 	int		status;
374 
375 	IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4,
376 	    ibmf_i_rmpp_sender_switch_flow_start, IBMF_TNF_TRACE, "",
377 	    "ibmf_i_rmpp_sender_switch_flow(): clientp = 0x%p, qp_hdl = 0x%p, "
378 	    "msgp = 0x%p, madp = 0x%p\n", tnf_opaque, clientp, clientp,
379 	    tnf_opaque, qp_hdl, qp_hdl, tnf_opaque, msg, msgimplp,
380 	    tnf_opaque, mad, mad);
381 
382 	rmpp_hdr = (ibmf_rmpp_hdr_t *)(mad + sizeof (ib_mad_hdr_t));
383 
384 	if (rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_ACK) {
385 
386 		IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
387 		    ibmf_i_rmpp_sender_switch_flow, IBMF_TNF_TRACE, "",
388 		    "ibmf_i_rmpp_sender_switch_flow(): %s\n", tnf_string, msg,
389 		    "ACK packet received, sending ACK");
390 
391 		(void) ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ACK,
392 		    IBMF_RMPP_STATUS_NORMAL, 0, 1, IBMF_NO_BLOCK);
393 
394 		/* set the response timer */
395 		ibmf_i_set_timer(ibmf_i_send_timeout, msgimplp,
396 		    IBMF_RESP_TIMER);
397 
398 	} else if (rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_DATA) {
399 
400 		IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
401 		    ibmf_i_rmpp_sender_switch_flow, IBMF_TNF_TRACE, "",
402 		    "ibmf_i_rmpp_sender_switch_flow(): %s\n", tnf_string, msg,
403 		    "DATA packet received, processing packet");
404 
405 		msgimplp->im_flags |= IBMF_MSG_FLAGS_RECV_RMPP;
406 		ibmf_i_rmpp_recvr_flow_main(clientp, qp_hdl, msgimplp, mad);
407 
408 	} else {
409 
410 		IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
411 		    ibmf_i_rmpp_sender_switch_flow, IBMF_TNF_TRACE, "",
412 		    "ibmf_i_rmpp_sender_switch_flow(): %s\n", tnf_string, msg,
413 		    "Unexpected packet received, sending ABORT BADT");
414 
415 		/* abort with status BadT */
416 		status = ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ABORT,
417 		    IBMF_RMPP_STATUS_BADT, 0, 0, IBMF_NO_BLOCK);
418 		if (status != IBMF_SUCCESS) {
419 			IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
420 			    ibmf_i_rmpp_sender_switch_flow, IBMF_TNF_TRACE, "",
421 			    "ibmf_i_rmpp_sender_switch_flow(): %s\n",
422 			    tnf_string, msg, "RMPP ABORT send failed");
423 			msgimplp->im_trans_state_flags |=
424 			    IBMF_TRANS_STATE_FLAG_SEND_DONE;
425 		}
426 
427 		mutex_enter(&clientp->ic_kstat_mutex);
428 		IBMF_ADD32_KSTATS(clientp, rmpp_errors, 1);
429 		mutex_exit(&clientp->ic_kstat_mutex);
430 
431 		rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
432 
433 		ibmf_i_set_timer(ibmf_i_err_terminate_timeout,
434 		    msgimplp, IBMF_RESP_TIMER);
435 	}
436 
437 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
438 	    ibmf_i_rmpp_sender_switch_flow_end, IBMF_TNF_TRACE, "",
439 	    "ibmf_i_rmpp_sender_switch_flow() exit\n");
440 }
441 
442 /*
443  * ibmf_i_rmpp_recvr_flow_main():
444  *	Perform RMPP receiver flow processing.
445  *	Refer to figure 176 "RMPP Receiver Main Flow Diagram" of
446  *	the InfiniBand Architecture Specification Volume 1, Release 1.1
447  */
448 static void
449 ibmf_i_rmpp_recvr_flow_main(ibmf_client_t *clientp, ibmf_qp_handle_t qp_hdl,
450     ibmf_msg_impl_t *msgimplp, uchar_t *mad)
451 {
452 	ibmf_rmpp_ctx_t	*rmpp_ctx = &msgimplp->im_rmpp_ctx;
453 	ibmf_rmpp_hdr_t *rmpp_hdr;
454 	ib_mad_hdr_t	*mad_hdr;
455 	uchar_t		*msgbufp;
456 	uchar_t		*datap;
457 	uint32_t	data_sz, offset, num_pkts;
458 	uint32_t	cl_hdr_sz, cl_data_sz, cl_hdr_off, cl_hdrdata_sz;
459 	size_t		buf_sz;
460 	int		status;
461 
462 	IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4,
463 	    ibmf_i_rmpp_recvr_flow_main_start, IBMF_TNF_TRACE, "",
464 	    "ibmf_i_rmpp_recvr_flow_main(): clientp = 0x%p, qp_hdl = 0x%p, "
465 	    "msgp = 0x%p, madp = 0x%p\n", tnf_opaque, clientp, clientp,
466 	    tnf_opaque, qp_hdl, qp_hdl, tnf_opaque, msg, msgimplp,
467 	    tnf_opaque, mad, mad);
468 
469 	rmpp_hdr = (ibmf_rmpp_hdr_t *)(mad + sizeof (ib_mad_hdr_t));
470 
471 	IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_rmpp_recvr_flow_main,
472 	    IBMF_TNF_TRACE, "", "ibmf_i_rmpp_recvr_flow_main(): "
473 	    "segnum = %d, es = %d, wl = %d\n", tnf_uint, segnum,
474 	    b2h32(rmpp_hdr->rmpp_segnum), tnf_uint, es, rmpp_ctx->rmpp_es,
475 	    tnf_uint, wl, rmpp_ctx->rmpp_wl);
476 
477 	/*
478 	 * check that this is the segment we expected;
479 	 * assume this check will succeed for the first segment since we cannot
480 	 * send an ACK if we haven't allocated the rmpp context yet
481 	 */
482 	if (b2h32(rmpp_hdr->rmpp_segnum) != rmpp_ctx->rmpp_es) {
483 
484 		IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
485 		    ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
486 		    "ibmf_i_rmpp_recvr_flow_main(): %s\n", tnf_string, msg,
487 		    "Unexpected segment number, discarding packet");
488 
489 		/* discard this packet by not processing it here */
490 
491 		/*
492 		 * If the receive buffer is not yet allocated, this is
493 		 * probably the first MAD received for the receive context.
494 		 * We need to set up the receive buffer before calling
495 		 * ibmf_i_send_rmpp() to send an ACK packet.
496 		 */
497 		if (msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL) {
498 			status = ibmf_setup_recvbuf_on_error(msgimplp, mad);
499 			if (status != IBMF_SUCCESS) {
500 				IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L2,
501 				    ibmf_i_rmpp_recvr_flow_main_err,
502 				    IBMF_TNF_ERROR, "",
503 				    "ibmf_i_rmpp_recvr_flow_main(): %s\n",
504 				    tnf_string, msg,
505 				    "ibmf_setup_recvbuf_on_error() failed");
506 				return;
507 			}
508 		}
509 
510 		/* send an ACK of ES - 1 if ES is greater than 1 */
511 		if (rmpp_ctx->rmpp_es > 1) {
512 			(void) ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ACK,
513 			    IBMF_RMPP_STATUS_NORMAL, rmpp_ctx->rmpp_es - 1,
514 			    rmpp_ctx->rmpp_es - 1 + IBMF_RMPP_DEFAULT_WIN_SZ,
515 			    IBMF_NO_BLOCK);
516 		}
517 
518 		/*
519 		 * reset the timer if we're still waiting for the first seg;
520 		 * this is the same timer that is normally set in send_compl
521 		 * NOTE: this should be in the IB spec's flowchart but isn't
522 		 */
523 		if (rmpp_ctx->rmpp_es == 1) {
524 			ibmf_i_set_timer(ibmf_i_send_timeout, msgimplp,
525 			    IBMF_RESP_TIMER);
526 		}
527 
528 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
529 		    ibmf_i_rmpp_recvr_flow_main_end, IBMF_TNF_TRACE, "",
530 		    "ibmf_i_rmpp_recvr_flow_main() exit\n");
531 		return;
532 	}
533 
534 	mad_hdr = (ib_mad_hdr_t *)mad;
535 
536 	ibmf_i_mgt_class_to_hdr_sz_off(mad_hdr->MgmtClass, &cl_hdr_sz,
537 	    &cl_hdr_off);
538 
539 	if ((rmpp_hdr->rmpp_flags & IBMF_RMPP_FLAGS_FIRST_PKT) ||
540 	    (b2h32(rmpp_hdr->rmpp_segnum) == 1)) {
541 
542 		/* first packet flag should be set and seg num should be 1 */
543 		if (((rmpp_hdr->rmpp_flags & IBMF_RMPP_FLAGS_FIRST_PKT) == 0) ||
544 		    (b2h32(rmpp_hdr->rmpp_segnum) != 1)) {
545 
546 			/*
547 			 * If the receive buffer is not yet allocated, this is
548 			 * probably the first MAD received for the receive ctx.
549 			 * We need to set up the receive buffer before calling
550 			 * ibmf_i_send_rmpp() to send an ABORT packet.
551 			 */
552 			if (msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL) {
553 				status = ibmf_setup_recvbuf_on_error(msgimplp,
554 				    mad);
555 				if (status != IBMF_SUCCESS) {
556 					IBMF_TRACE_1(IBMF_TNF_NODEBUG,
557 					    DPRINT_L2,
558 					    ibmf_i_rmpp_recvr_flow_main_err,
559 					    IBMF_TNF_ERROR, "",
560 					    "ibmf_i_rmpp_recvr_flow_main(): "
561 					    "%s\n", tnf_string, msg,
562 					    "ibmf_setup_recvbuf_on_error() "
563 					    "failed");
564 					return;
565 				}
566 			}
567 
568 			/* abort with status BadT */
569 			status = ibmf_i_send_rmpp(msgimplp,
570 			    IBMF_RMPP_TYPE_ABORT, IBMF_RMPP_STATUS_IFSN,
571 			    0, 0, IBMF_NO_BLOCK);
572 			if (status != IBMF_SUCCESS) {
573 				IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
574 				    ibmf_i_rmpp_recvr_flow_main,
575 				    IBMF_TNF_TRACE, "",
576 				    "ibmf_i_rmpp_recvr_flow_main(): %s\n",
577 				    tnf_string, msg, "RMPP ABORT send failed");
578 				msgimplp->im_trans_state_flags |=
579 				    IBMF_TRANS_STATE_FLAG_SEND_DONE;
580 			}
581 
582 			mutex_enter(&clientp->ic_kstat_mutex);
583 			IBMF_ADD32_KSTATS(clientp, rmpp_errors, 1);
584 			mutex_exit(&clientp->ic_kstat_mutex);
585 
586 			IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
587 			    ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
588 			    "ibmf_i_rmpp_recvr_flow_main(): %s\n",
589 			    tnf_string, msg, "Inconsistent first and segment "
590 			    "number detected, sending ABORT IFSN");
591 
592 			rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
593 
594 			ibmf_i_unset_timer(msgimplp, IBMF_TRANS_TIMER);
595 
596 			ibmf_i_set_timer(ibmf_i_err_terminate_timeout,
597 			    msgimplp, IBMF_RESP_TIMER);
598 
599 			IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
600 			    ibmf_i_rmpp_recvr_flow_main_end, IBMF_TNF_TRACE,
601 			    "", "ibmf_i_rmpp_recvr_flow_main() exit\n");
602 			return;
603 		}
604 
605 		IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
606 		    ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
607 		    "ibmf_i_rmpp_recvr_flow_main(): %s\n", tnf_string, msg,
608 		    "Segment number 1 received:", tnf_opaque, msgp, msgimplp);
609 
610 		cl_data_sz = MAD_SIZE_IN_BYTES -
611 		    sizeof (ib_mad_hdr_t) - cl_hdr_off - cl_hdr_sz;
612 
613 		cl_hdrdata_sz = MAD_SIZE_IN_BYTES -
614 		    sizeof (ib_mad_hdr_t) - cl_hdr_off;
615 
616 		/*
617 		 * Calculate the number of packets by dividing the payload
618 		 * length in the RMPP header by the payload size for
619 		 * a single packet of that management class (including the
620 		 * class header).
621 		 */
622 		buf_sz = b2h32(rmpp_hdr->rmpp_pyldlen_nwl);
623 		if ((buf_sz % cl_hdrdata_sz) != 0)
624 			num_pkts = (buf_sz / cl_hdrdata_sz) + 1;
625 		else {
626 			if (buf_sz > 0)
627 				num_pkts = buf_sz / cl_hdrdata_sz;
628 			else
629 				num_pkts = 1;
630 		}
631 
632 		/*
633 		 * If the payload length of the message is not specified
634 		 * in the first packet's RMPP header, we create a
635 		 * temporary receive buffer with space for data payloads
636 		 * of IBMF_BUF_PKTS packets. If the number of packets
637 		 * received exceeds the capacity in the receive buffer,
638 		 * the temporary receive buffer will be freed up, and
639 		 * a larger temporary receive buffer will be allocated.
640 		 * When the last packet is received, the final receive
641 		 * buffer will be allocated with the real size of the message.
642 		 * The data will be copied from the old buffer to the new
643 		 * buffer.
644 		 */
645 		if (b2h32(rmpp_hdr->rmpp_pyldlen_nwl) != 0) {
646 			/*
647 			 * rmpp_pyld_len is the total length of just the
648 			 * class data. Class headers from each packet are
649 			 * not included in this calculation.
650 			 */
651 			msgimplp->im_msgbufs_recv.im_bufs_cl_data_len =
652 			    rmpp_ctx->rmpp_pyld_len =
653 			    b2h32(rmpp_hdr->rmpp_pyldlen_nwl) -
654 			    (num_pkts * cl_hdr_sz);
655 		} else {
656 			msgimplp->im_msgbufs_recv.im_bufs_cl_data_len =
657 			    rmpp_ctx->rmpp_pyld_len =
658 			    IBMF_BUF_PKTS * cl_data_sz;
659 			rmpp_ctx->rmpp_flags |= IBMF_CTX_RMPP_FLAGS_DYN_PYLD;
660 		}
661 
662 		ASSERT(msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL);
663 
664 		/* allocate memory for the message data */
665 		msgimplp->im_msgbufs_recv.im_bufs_mad_hdr =
666 		    (ib_mad_hdr_t *)kmem_zalloc(sizeof (ib_mad_hdr_t) +
667 		    cl_hdr_off + cl_hdr_sz + rmpp_ctx->rmpp_pyld_len,
668 		    KM_NOSLEEP);
669 		if (msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL) {
670 
671 			IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
672 			    ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
673 			    "ibmf_i_rmpp_recvr_flow_main(): %s\n",
674 			    tnf_string, msg,
675 			    "mem allocation failure (known rmpp payload)");
676 
677 			ibmf_i_terminate_transaction(
678 			    msgimplp->im_client, msgimplp,
679 			    IBMF_NO_MEMORY);
680 
681 			IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
682 			    ibmf_i_rmpp_recvr_flow_main_end, IBMF_TNF_TRACE,
683 			    "", "ibmf_i_rmpp_recvr_flow_main() exit\n");
684 			return;
685 		}
686 		mutex_enter(&clientp->ic_kstat_mutex);
687 		IBMF_ADD32_KSTATS(clientp, recv_bufs_alloced, 1);
688 		mutex_exit(&clientp->ic_kstat_mutex);
689 
690 		msgbufp = (uchar_t *)msgimplp->im_msgbufs_recv.im_bufs_mad_hdr;
691 
692 		/* copy the MAD and class header */
693 		bcopy((const void *)mad, (void *)msgbufp,
694 		    sizeof (ib_mad_hdr_t) + cl_hdr_off + cl_hdr_sz);
695 
696 		offset = sizeof (ib_mad_hdr_t) + cl_hdr_off;
697 
698 		/* initialize class header pointer */
699 		if (cl_hdr_sz == 0) {
700 			msgimplp->im_msgbufs_recv.im_bufs_cl_hdr = NULL;
701 		} else {
702 			msgimplp->im_msgbufs_recv.im_bufs_cl_hdr =
703 			    (void *)(msgbufp + offset);
704 		}
705 		msgimplp->im_msgbufs_recv.im_bufs_cl_hdr_len = cl_hdr_sz;
706 
707 		offset += cl_hdr_sz;
708 
709 		/* initialize data area pointer */
710 		msgimplp->im_msgbufs_recv.im_bufs_cl_data =
711 		    (void *)(msgbufp + offset);
712 
713 		rmpp_ctx->rmpp_data_offset = 0;
714 
715 		cl_data_sz = MAD_SIZE_IN_BYTES -
716 		    sizeof (ib_mad_hdr_t) - cl_hdr_off - cl_hdr_sz;
717 
718 		rmpp_ctx->rmpp_pkt_data_sz = cl_data_sz;
719 
720 		/*
721 		 * calculate number of expected packets for transaction
722 		 * timeout calculation
723 		 */
724 		if (rmpp_ctx->rmpp_flags & IBMF_CTX_RMPP_FLAGS_DYN_PYLD) {
725 
726 			/*
727 			 * if the payload length is not specified in
728 			 * the first packet, just guess how many packets
729 			 * might arrive
730 			 */
731 			msgimplp->im_rmpp_ctx.rmpp_num_pkts = 100;
732 		} else {
733 			msgimplp->im_rmpp_ctx.rmpp_num_pkts =
734 			    rmpp_ctx->rmpp_pyld_len / cl_data_sz;
735 
736 			/* round up */
737 			if ((rmpp_ctx->rmpp_pyld_len % cl_data_sz) != 0)
738 				msgimplp->im_rmpp_ctx.rmpp_num_pkts++;
739 		}
740 
741 		/* set the transaction timer if there are more packets */
742 		if ((rmpp_hdr->rmpp_flags & IBMF_RMPP_FLAGS_LAST_PKT) == 0) {
743 
744 			IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
745 			    ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
746 			    "ibmf_i_rmpp_recvr_flow_main(): %s\n",
747 			    tnf_string, msg,
748 			    "First pkt recvd; setting trans timer: ",
749 			    tnf_opaque, msg, msgimplp);
750 
751 			IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
752 			    ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
753 			    "ibmf_i_rmpp_recvr_flow_main(): setting trans"
754 			    " timer %p %d\n", tnf_opaque, msg, msgimplp,
755 			    tnf_opaque, timeout_id, msgimplp->im_rp_timeout_id);
756 
757 			ibmf_i_set_timer(ibmf_i_recv_timeout, msgimplp,
758 			    IBMF_TRANS_TIMER);
759 		}
760 	}
761 
762 	offset = sizeof (ib_mad_hdr_t) + cl_hdr_off + cl_hdr_sz;
763 
764 	/*
765 	 * copy the data from the packet into the data buffer in
766 	 * the message.
767 	 */
768 
769 	if (rmpp_hdr->rmpp_flags & IBMF_RMPP_FLAGS_LAST_PKT)
770 		data_sz = b2h32(rmpp_hdr->rmpp_pyldlen_nwl) - cl_hdr_sz;
771 	else
772 		data_sz = rmpp_ctx->rmpp_pkt_data_sz;
773 
774 	/* if a payload length was specified and we've met or exceeded it */
775 	if (((data_sz + rmpp_ctx->rmpp_data_offset) >=
776 	    rmpp_ctx->rmpp_pyld_len) &&
777 	    ((rmpp_ctx->rmpp_flags & IBMF_CTX_RMPP_FLAGS_DYN_PYLD) == 0)) {
778 
779 		/* last packet flag should be set */
780 		if ((rmpp_hdr->rmpp_flags & IBMF_RMPP_FLAGS_LAST_PKT) == 0) {
781 
782 			/* abort with status Incon. last and payload length */
783 			status = ibmf_i_send_rmpp(msgimplp,
784 			    IBMF_RMPP_TYPE_ABORT, IBMF_RMPP_STATUS_ILPL,
785 			    0, 0, IBMF_NO_BLOCK);
786 			if (status != IBMF_SUCCESS) {
787 				IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
788 				    ibmf_i_rmpp_recvr_flow_main,
789 				    IBMF_TNF_TRACE, "",
790 				    "ibmf_i_rmpp_recvr_flow_main(): %s\n",
791 				    tnf_string, msg, "RMPP ABORT send failed");
792 				msgimplp->im_trans_state_flags |=
793 				    IBMF_TRANS_STATE_FLAG_SEND_DONE;
794 			}
795 
796 			mutex_enter(&clientp->ic_kstat_mutex);
797 			IBMF_ADD32_KSTATS(clientp, rmpp_errors, 1);
798 			mutex_exit(&clientp->ic_kstat_mutex);
799 
800 			IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
801 			    ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
802 			    "ibmf_i_rmpp_recvr_flow_main(): %s\n",
803 			    tnf_string, msg,
804 			    "Inconsistent last and payload length detected,"
805 			    " sending ABORT ILPL, unsetting trans timer");
806 
807 			rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
808 
809 			ibmf_i_unset_timer(msgimplp, IBMF_TRANS_TIMER);
810 
811 			ibmf_i_set_timer(ibmf_i_err_terminate_timeout,
812 			    msgimplp, IBMF_RESP_TIMER);
813 
814 			IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
815 			    ibmf_i_rmpp_recvr_flow_main_end, IBMF_TNF_TRACE,
816 			    "", "ibmf_i_rmpp_recvr_flow_main() exit\n");
817 
818 			return;
819 		}
820 	} else if (((data_sz + rmpp_ctx->rmpp_data_offset) >=
821 	    rmpp_ctx->rmpp_pyld_len) &&
822 	    ((rmpp_ctx->rmpp_flags & IBMF_CTX_RMPP_FLAGS_DYN_PYLD) != 0) &&
823 	    ((rmpp_hdr->rmpp_flags & IBMF_RMPP_FLAGS_LAST_PKT) == 0)) {
824 
825 		/*
826 		 * If the payload length was not specified in the first
827 		 * packet's RMPP header, we have a temporary receive buffer
828 		 * the size of which will be exceeded with this incoming
829 		 * packet. We need to allocate a new temporary receive buffer
830 		 * with an additional IBMF_BUF_PKTS data payloads.
831 		 */
832 		ib_mad_hdr_t	*old_buf;
833 		size_t		prev_pyld_len;
834 
835 		old_buf = msgimplp->im_msgbufs_recv.im_bufs_mad_hdr;
836 		prev_pyld_len = rmpp_ctx->rmpp_pyld_len;
837 
838 		rmpp_ctx->rmpp_pyld_len +=
839 		    IBMF_BUF_PKTS * rmpp_ctx->rmpp_pkt_data_sz;
840 		msgimplp->im_msgbufs_recv.im_bufs_cl_data_len =
841 			    rmpp_ctx->rmpp_pyld_len;
842 		msgimplp->im_msgbufs_recv.im_bufs_mad_hdr =
843 		    (ib_mad_hdr_t *)kmem_zalloc(sizeof (ib_mad_hdr_t) +
844 		    cl_hdr_off + cl_hdr_sz + rmpp_ctx->rmpp_pyld_len,
845 		    KM_NOSLEEP);
846 		if (msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL) {
847 
848 			IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
849 			    ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
850 			    "ibmf_i_rmpp_recvr_flow_main(): %s, allocsz = %d\n",
851 			    tnf_string, msg,
852 			    "mem allocation failure (unknown rmpp payload)",
853 			    tnf_uint, alloc_size,
854 			    sizeof (ib_mad_hdr_t) + cl_hdr_off + cl_hdr_sz +
855 			    rmpp_ctx->rmpp_pyld_len);
856 
857 			ibmf_i_terminate_transaction(
858 			    msgimplp->im_client, msgimplp,
859 			    IBMF_NO_MEMORY);
860 
861 			IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
862 			    ibmf_i_rmpp_recvr_flow_main_end, IBMF_TNF_TRACE,
863 			    "", "ibmf_i_rmpp_recvr_flow_main() exit\n");
864 			return;
865 		}
866 		mutex_enter(&clientp->ic_kstat_mutex);
867 		IBMF_ADD32_KSTATS(clientp, recv_bufs_alloced, 1);
868 		mutex_exit(&clientp->ic_kstat_mutex);
869 
870 		msgbufp = (uchar_t *)msgimplp->im_msgbufs_recv.im_bufs_mad_hdr;
871 
872 		/* copy the MAD and class header */
873 		bcopy((const void *)old_buf, (void *)msgbufp,
874 		    sizeof (ib_mad_hdr_t) + cl_hdr_off + cl_hdr_sz +
875 		    prev_pyld_len);
876 
877 		kmem_free(old_buf, sizeof (ib_mad_hdr_t) + cl_hdr_off +
878 		    cl_hdr_sz + prev_pyld_len);
879 	}
880 
881 	/* don't overflow buffer */
882 	if (rmpp_ctx->rmpp_data_offset + data_sz >
883 	    rmpp_ctx->rmpp_pyld_len) {
884 		data_sz = rmpp_ctx->rmpp_pyld_len -
885 		    rmpp_ctx->rmpp_data_offset;
886 	}
887 
888 	datap = (uchar_t *)msgimplp->im_msgbufs_recv.im_bufs_cl_data;
889 
890 	bcopy((void *)&mad[offset],
891 	    (void *)(datap + rmpp_ctx->rmpp_data_offset), data_sz);
892 
893 	rmpp_ctx->rmpp_data_offset += data_sz;
894 
895 	rmpp_ctx->rmpp_es++;
896 
897 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_rmpp_recvr_flow_main,
898 	    IBMF_TNF_TRACE, "", "ibmf_i_rmpp_recvr_flow_main(): es = %d\n",
899 	    tnf_uint, es, rmpp_ctx->rmpp_es);
900 
901 	if (rmpp_hdr->rmpp_flags & IBMF_RMPP_FLAGS_LAST_PKT) {
902 
903 		/*
904 		 * Since this is the last packet, we finally know the
905 		 * size of the receive buffer we need to allocate.
906 		 * Allocate the needed size and free the temporary receive
907 		 * buffer.
908 		 */
909 		if ((rmpp_ctx->rmpp_flags & IBMF_CTX_RMPP_FLAGS_DYN_PYLD) !=
910 		    0) {
911 			ib_mad_hdr_t	*old_buf;
912 			size_t		prev_pyld_len;
913 
914 			rmpp_ctx->rmpp_flags &= ~IBMF_CTX_RMPP_FLAGS_DYN_PYLD;
915 			old_buf = msgimplp->im_msgbufs_recv.im_bufs_mad_hdr;
916 			prev_pyld_len = rmpp_ctx->rmpp_pyld_len;
917 			rmpp_ctx->rmpp_pyld_len = rmpp_ctx->rmpp_data_offset;
918 			msgimplp->im_msgbufs_recv.im_bufs_cl_data_len =
919 			    rmpp_ctx->rmpp_pyld_len;
920 			msgimplp->im_msgbufs_recv.im_bufs_mad_hdr =
921 			    (ib_mad_hdr_t *)kmem_zalloc(sizeof (ib_mad_hdr_t) +
922 			    cl_hdr_off + cl_hdr_sz + rmpp_ctx->rmpp_pyld_len,
923 			    KM_NOSLEEP);
924 			if (msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL) {
925 				IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
926 				    ibmf_i_rmpp_recvr_flow_main,
927 				    IBMF_TNF_TRACE, "",
928 				    "ibmf_i_rmpp_recvr_flow_main(): %s\n",
929 				    tnf_string, msg,
930 				    "mem allocation failure (final payload)");
931 				ibmf_i_terminate_transaction(
932 				    msgimplp->im_client, msgimplp,
933 				    IBMF_NO_MEMORY);
934 				IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
935 				    ibmf_i_rmpp_recvr_flow_main_end,
936 				    IBMF_TNF_TRACE, "",
937 				    "ibmf_i_rmpp_recvr_flow_main() exit\n");
938 				return;
939 			}
940 			mutex_enter(&clientp->ic_kstat_mutex);
941 			IBMF_ADD32_KSTATS(clientp, recv_bufs_alloced, 1);
942 			mutex_exit(&clientp->ic_kstat_mutex);
943 
944 			msgbufp = (uchar_t *)
945 			    msgimplp->im_msgbufs_recv.im_bufs_mad_hdr;
946 
947 			/* copy the data to the new buffer */
948 			bcopy((const void *)old_buf, (void *)msgbufp,
949 			    sizeof (ib_mad_hdr_t) + cl_hdr_off + cl_hdr_sz +
950 			    rmpp_ctx->rmpp_pyld_len);
951 
952 			offset = sizeof (ib_mad_hdr_t) + cl_hdr_off;
953 
954 			/* initialize class header pointer */
955 			if (cl_hdr_sz == 0) {
956 				msgimplp->im_msgbufs_recv.im_bufs_cl_hdr = NULL;
957 			} else {
958 				msgimplp->im_msgbufs_recv.im_bufs_cl_hdr =
959 				    (void *)(msgbufp + offset);
960 			}
961 			msgimplp->im_msgbufs_recv.im_bufs_cl_hdr_len =
962 			    cl_hdr_sz;
963 
964 			offset += cl_hdr_sz;
965 
966 			/* initialize data area pointer */
967 			msgimplp->im_msgbufs_recv.im_bufs_cl_data =
968 			    (void *)(msgbufp + offset);
969 
970 			kmem_free(old_buf, sizeof (ib_mad_hdr_t) + cl_hdr_off +
971 			    cl_hdr_sz + prev_pyld_len);
972 		}
973 
974 		IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
975 		    ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
976 		    "ibmf_i_rmpp_recvr_flow_main(): %s, msgp = 0x%p\n",
977 		    tnf_string, msg,
978 		    "Last pkt rcvd; state to recv_term, sending ack",
979 		    tnf_opaque, msgp, msgimplp);
980 
981 		rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_RECEVR_TERMINATE;
982 
983 		status = ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ACK,
984 		    IBMF_RMPP_STATUS_NORMAL, rmpp_ctx->rmpp_es - 1,
985 		    rmpp_ctx->rmpp_es - 1 + IBMF_RMPP_DEFAULT_WIN_SZ,
986 		    IBMF_NO_BLOCK);
987 		if (status != IBMF_SUCCESS) {
988 			IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
989 			    ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
990 			    "ibmf_i_rmpp_recvr_flow_main(): %s\n",
991 			    tnf_string, msg, "RMPP ACK send failed");
992 			msgimplp->im_trans_state_flags |=
993 			    IBMF_TRANS_STATE_FLAG_SEND_DONE;
994 		}
995 
996 		/* unset the transaction timer if it's not the first segment */
997 		if ((rmpp_hdr->rmpp_flags & IBMF_RMPP_FLAGS_FIRST_PKT) == 0) {
998 			IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
999 			    ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
1000 			    "ibmf_i_rmpp_recvr_flow_main(): %s, msgp = 0x%p\n",
1001 			    tnf_string, msg, "Last, but not first segment",
1002 			    tnf_opaque, msgp, msgimplp);
1003 			IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
1004 			    ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
1005 			    "ibmf_i_rmpp_recvr_flow_main(): unsetting timer "
1006 			    "%p %d\n", tnf_opaque, msgp, msgimplp,
1007 			    tnf_opaque, timeout_id, msgimplp->im_rp_timeout_id);
1008 
1009 			ibmf_i_unset_timer(msgimplp, IBMF_TRANS_TIMER);
1010 		}
1011 
1012 		IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
1013 		    ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
1014 		    "ibmf_i_rmpp_recvr_flow_main(): %s, msgp = 0x%p\n",
1015 		    tnf_string, msg,
1016 		    "Last pkt rcvd; setting resp timer",
1017 		    tnf_opaque, msgp, msgimplp);
1018 
1019 		/*
1020 		 * The RMPP receive transaction has been broken
1021 		 * up into two parts. At this point in the
1022 		 * transaction, all the data has been received.
1023 		 * From the perspective of the client, the transaction
1024 		 * is complete. So, control is returned to the client
1025 		 * at this point. However, the RMPP protocol requires
1026 		 * a wait after receiving the last data packet, so that,
1027 		 * duplicate packets may be absorbed. This wait is
1028 		 * implemented in the second part of the transaction under
1029 		 * a duplicate message context.
1030 		 * The regular message context is marked as done in
1031 		 * ibmf_i_terminate_transaction().
1032 		 * The IBMF_MSG_FLAGS_SET_TERMINATION flag indicates
1033 		 * that the duplicate message context needs to be created
1034 		 * to handle the termination loop.
1035 		 */
1036 		IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
1037 		    ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
1038 		    "ibmf_i_rmpp_recvr_flow_main(): last packet, "
1039 		    " returning data to client for message %p\n",
1040 		    tnf_opaque, msgp, msgimplp);
1041 
1042 		ibmf_i_terminate_transaction(clientp, msgimplp, IBMF_SUCCESS);
1043 
1044 		/* Mark this message for early termination */
1045 		msgimplp->im_flags |= IBMF_MSG_FLAGS_SET_TERMINATION;
1046 
1047 		return;
1048 	}
1049 
1050 	if (b2h32(rmpp_hdr->rmpp_segnum) == rmpp_ctx->rmpp_wl) {
1051 		IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L3,
1052 		    ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
1053 		    "ibmf_i_rmpp_recvr_flow_main(): %s, msgp = 0x%p"
1054 		    "segnum = %d, wl = %d\n", tnf_string, msg,
1055 		    "Last packet in window received", tnf_opaque, msgimplp,
1056 		    msgimplp, tnf_opaque, seg, b2h32(rmpp_hdr->rmpp_segnum),
1057 		    tnf_opaque, wl, rmpp_ctx->rmpp_wl);
1058 
1059 		(void) ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ACK,
1060 		    IBMF_RMPP_STATUS_NORMAL,
1061 		    rmpp_ctx->rmpp_es - 1,
1062 		    rmpp_ctx->rmpp_es - 1 +
1063 		    IBMF_RMPP_DEFAULT_WIN_SZ, IBMF_NO_BLOCK);
1064 
1065 		/* update the window */
1066 		rmpp_ctx->rmpp_wl += IBMF_RMPP_DEFAULT_WIN_SZ;
1067 
1068 	} else {
1069 
1070 		IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
1071 		    ibmf_i_rmpp_recvr_flow_main, IBMF_TNF_TRACE, "",
1072 		    "ibmf_i_rmpp_recvr_flow_main(): %s\n",
1073 		    tnf_string, msg, "Packet in window received");
1074 
1075 	}
1076 
1077 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
1078 	    ibmf_i_rmpp_recvr_flow_main_end, IBMF_TNF_TRACE, "",
1079 	    "ibmf_i_rmpp_recvr_flow_main() exit\n");
1080 }
1081 
1082 /*
1083  * ibmf_i_rmpp_recvr_active_flow():
1084  *	Perform RMPP receiver flow initiation processing.
1085  *	Refer to figure 176 "RMPP Receiver Main Flow Diagram" of
1086  *	the InfiniBand Architecture Specification Volume 1, Release 1.1
1087  */
1088 static void
1089 ibmf_i_rmpp_recvr_active_flow(ibmf_client_t *clientp, ibmf_qp_handle_t qp_hdl,
1090     ibmf_msg_impl_t *msgimplp, uchar_t *mad)
1091 {
1092 	ibmf_rmpp_ctx_t	*rmpp_ctx = &msgimplp->im_rmpp_ctx;
1093 	ibmf_rmpp_hdr_t *rmpp_hdr;
1094 	uint32_t	abort_status;
1095 	int		status;
1096 
1097 	IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4,
1098 	    ibmf_i_rmpp_recvr_active_flow_start, IBMF_TNF_TRACE, "",
1099 	    "ibmf_i_rmpp_recvr_active_flow(): clientp = 0x%p, qp_hdl = 0x%p, "
1100 	    "msgp = 0x%p, madp = 0x%p\n", tnf_opaque, clientp, clientp,
1101 	    tnf_opaque, qp_hdl, qp_hdl, tnf_opaque, msg, msgimplp,
1102 	    tnf_opaque, mad, mad);
1103 
1104 	rmpp_hdr = (ibmf_rmpp_hdr_t *)(mad + sizeof (ib_mad_hdr_t));
1105 
1106 	if (rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_ACK) {
1107 
1108 		/* discard this packet by not processing it here */
1109 
1110 		IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
1111 		    ibmf_i_rmpp_recvr_active_flow, IBMF_TNF_TRACE, "",
1112 		    "ibmf_i_rmpp_recvr_active_flow(): %s\n", tnf_string, msg,
1113 		    "ACK packet received, discarding packet");
1114 
1115 		/*
1116 		 * reset the timer if we're still waiting for the first seg;
1117 		 * this is the same timer that is normally set in send_compl
1118 		 * NOTE: this should be in the IB spec's flowchart but isn't
1119 		 */
1120 		if (rmpp_ctx->rmpp_es == 1) {
1121 			ibmf_i_set_timer(ibmf_i_send_timeout, msgimplp,
1122 			    IBMF_RESP_TIMER);
1123 		}
1124 
1125 		return;
1126 	}
1127 
1128 	if (rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_DATA) {
1129 
1130 		IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
1131 		    ibmf_i_rmpp_recvr_active_flow, IBMF_TNF_TRACE, "",
1132 		    "ibmf_i_rmpp_recvr_active_flow(): %s\n", tnf_string, msg,
1133 		    "DATA packet received, processing packet");
1134 
1135 		ibmf_i_rmpp_recvr_flow_main(clientp, qp_hdl, msgimplp, mad);
1136 
1137 	} else if ((rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_STOP) ||
1138 	    (rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_ABORT)) {
1139 
1140 		abort_status = rmpp_hdr->rmpp_status;
1141 
1142 		IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L2,
1143 		    ibmf_i_rmpp_recvr_active_flow, IBMF_TNF_TRACE, "",
1144 		    "ibmf_i_rmpp_recvr_active_flow(): %s, status = %d\n",
1145 		    tnf_string, msg,
1146 		    "STOP/ABORT packet received, terminating transaction",
1147 		    tnf_uint, abort_status, abort_status);
1148 
1149 		/* discard the packet and terminate the transaction */
1150 		rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
1151 		msgimplp->im_trans_state_flags |=
1152 		    IBMF_TRANS_STATE_FLAG_SEND_DONE;
1153 
1154 		ibmf_i_unset_timer(msgimplp, IBMF_TRANS_TIMER);
1155 
1156 		ibmf_i_set_timer(ibmf_i_err_terminate_timeout,
1157 		    msgimplp, IBMF_RESP_TIMER);
1158 
1159 	} else {
1160 
1161 		IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
1162 		    ibmf_i_rmpp_recvr_active_flow, IBMF_TNF_TRACE, "",
1163 		    "ibmf_i_rmpp_recvr_active_flow(): %s\n", tnf_string, msg,
1164 		    "Unrecognized packet received, terminating transaction");
1165 
1166 		/* abort with status BadT */
1167 		status = ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ABORT,
1168 		    IBMF_RMPP_STATUS_BADT, 0, 0, IBMF_NO_BLOCK);
1169 		if (status != IBMF_SUCCESS) {
1170 			IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
1171 			    ibmf_i_rmpp_recvr_active_flow, IBMF_TNF_TRACE, "",
1172 			    "ibmf_i_rmpp_recvr_active_flow(): %s\n",
1173 			    tnf_string, msg, "RMPP ABORT send failed");
1174 			msgimplp->im_trans_state_flags |=
1175 			    IBMF_TRANS_STATE_FLAG_SEND_DONE;
1176 		}
1177 
1178 		rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
1179 
1180 		mutex_enter(&clientp->ic_kstat_mutex);
1181 		IBMF_ADD32_KSTATS(clientp, rmpp_errors, 1);
1182 		mutex_exit(&clientp->ic_kstat_mutex);
1183 
1184 		ibmf_i_unset_timer(msgimplp, IBMF_TRANS_TIMER);
1185 
1186 		ibmf_i_set_timer(ibmf_i_err_terminate_timeout,
1187 		    msgimplp, IBMF_RESP_TIMER);
1188 	}
1189 
1190 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
1191 	    ibmf_i_rmpp_recvr_active_flow_end, IBMF_TNF_TRACE, "",
1192 	    "ibmf_i_rmpp_recvr_active_flow() exit\n");
1193 }
1194 
1195 /*
1196  * ibmf_i_rmpp_recvr_term_flow():
1197  *	Perform RMPP receiver termination flow processing.
1198  *	Refer to figure 177 "RMPP Receiver Termination Flow Diagram" of
1199  *	the InfiniBand Architecture Specification Volume 1, Release 1.1
1200  */
1201 static void
1202 ibmf_i_rmpp_recvr_term_flow(ibmf_client_t *clientp, ibmf_qp_handle_t qp_hdl,
1203     ibmf_msg_impl_t *msgimplp, uchar_t *mad)
1204 {
1205 	ibmf_rmpp_ctx_t	*rmpp_ctx = &msgimplp->im_rmpp_ctx;
1206 	ibmf_rmpp_hdr_t *rmpp_hdr;
1207 	int		status;
1208 
1209 	IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4,
1210 	    ibmf_i_rmpp_recvr_term_flow_start, IBMF_TNF_TRACE, "",
1211 	    "ibmf_i_rmpp_recvr_term_flow(): clientp = 0x%p, qp_hdl = 0x%p, "
1212 	    "msgp = 0x%p, madp = 0x%p\n", tnf_opaque, clientp, clientp,
1213 	    tnf_opaque, qp_hdl, qp_hdl, tnf_opaque, msg, msgimplp,
1214 	    tnf_opaque, mad, mad);
1215 
1216 	rmpp_hdr = (ibmf_rmpp_hdr_t *)(mad + sizeof (ib_mad_hdr_t));
1217 
1218 	if (rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_DATA) {
1219 
1220 		IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
1221 		    ibmf_i_rmpp_recvr_term_flow, IBMF_TNF_TRACE, "",
1222 		    "ibmf_i_rmpp_recvr_term_flow(): %s\n", tnf_string, msg,
1223 		    "Data packet received, resending ACK");
1224 
1225 		(void) ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ACK,
1226 		    IBMF_RMPP_STATUS_NORMAL, rmpp_ctx->rmpp_es - 1,
1227 		    rmpp_ctx->rmpp_es - 1 + IBMF_RMPP_DEFAULT_WIN_SZ,
1228 		    IBMF_NO_BLOCK);
1229 
1230 		IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
1231 		    ibmf_i_rmpp_recvr_term_flow, IBMF_TNF_TRACE, "",
1232 		    "ibmf_i_rmpp_recvr_term_flow(): setting resp timer %d %p\n",
1233 		    tnf_opaque, msgimplp, msgimplp, tnf_opaque,
1234 		    timeout_id, msgimplp->im_rp_timeout_id);
1235 
1236 		/* set the response timer */
1237 		ibmf_i_set_timer(ibmf_i_recv_timeout, msgimplp,
1238 		    IBMF_RESP_TIMER);
1239 
1240 	} else if (rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_ACK) {
1241 
1242 		IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
1243 		    ibmf_i_rmpp_recvr_term_flow, IBMF_TNF_TRACE, "",
1244 		    "ibmf_i_rmpp_recvr_term_flow(): %s, msgp = 0x%p\n",
1245 		    tnf_string, msg, "ACK packet received",
1246 		    tnf_opaque, msgimplp, msgimplp);
1247 
1248 		if (rmpp_ctx->rmpp_is_ds) {
1249 			/*
1250 			 * received ACK from sender which is indication that
1251 			 * we can send response; notify client that data has
1252 			 * arrived; it will call msg_transport to send response
1253 			 */
1254 			IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
1255 			    ibmf_i_rmpp_recvr_term_flow, IBMF_TNF_TRACE, "",
1256 			    "ibmf_i_rmpp_recvr_term_flow(): %s, msgp = 0x%p\n",
1257 			    tnf_string, msg,
1258 			    "Received final ack for double-sided trans",
1259 			    tnf_opaque, msgimplp, msgimplp);
1260 
1261 			/*
1262 			 * successful termination
1263 			 */
1264 			rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_DONE;
1265 			ibmf_i_terminate_transaction(clientp, msgimplp,
1266 			    IBMF_SUCCESS);
1267 
1268 		} else {
1269 
1270 			IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L2,
1271 			    ibmf_i_rmpp_recvr_term_flow, IBMF_TNF_TRACE, "",
1272 			    "ibmf_i_rmpp_recvr_term_flow(): %s, msgp = 0x%p\n",
1273 			    tnf_string, msg, "Received ACK while in recv_term "
1274 			    "state for single sided trans",
1275 			    tnf_opaque, msgimplp, msgimplp);
1276 
1277 			/* abort with status BadT */
1278 			(void) ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ABORT,
1279 			    IBMF_RMPP_STATUS_BADT, 0, 0, IBMF_NO_BLOCK);
1280 
1281 			rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
1282 
1283 			ibmf_i_unset_timer(msgimplp, IBMF_TRANS_TIMER);
1284 
1285 			ibmf_i_set_timer(ibmf_i_err_terminate_timeout,
1286 			    msgimplp, IBMF_RESP_TIMER);
1287 		}
1288 
1289 	} else {
1290 
1291 		IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
1292 		    ibmf_i_rmpp_recvr_term_flow, IBMF_TNF_TRACE, "",
1293 		    "ibmf_i_rmpp_recvr_term_flow(): %s\n", tnf_string, msg,
1294 		    "Unexpected packet received, sending ABORT BADT");
1295 
1296 		/* abort with status BadT */
1297 		status = ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ABORT,
1298 		    IBMF_RMPP_STATUS_BADT, 0, 0, IBMF_NO_BLOCK);
1299 		if (status != IBMF_SUCCESS) {
1300 			IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
1301 			    ibmf_i_rmpp_recvr_term_flow, IBMF_TNF_TRACE, "",
1302 			    "ibmf_i_rmpp_recvr_term_flow(): %s\n",
1303 			    tnf_string, msg, "RMPP ABORT send failed");
1304 			msgimplp->im_trans_state_flags |=
1305 			    IBMF_TRANS_STATE_FLAG_SEND_DONE;
1306 		}
1307 
1308 		rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
1309 
1310 		mutex_enter(&clientp->ic_kstat_mutex);
1311 		IBMF_ADD32_KSTATS(clientp, rmpp_errors, 1);
1312 		mutex_exit(&clientp->ic_kstat_mutex);
1313 
1314 		ibmf_i_unset_timer(msgimplp, IBMF_TRANS_TIMER);
1315 
1316 		ibmf_i_set_timer(ibmf_i_err_terminate_timeout,
1317 		    msgimplp, IBMF_RESP_TIMER);
1318 
1319 	}
1320 
1321 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
1322 	    ibmf_i_rmpp_recvr_term_flow_end, IBMF_TNF_TRACE, "",
1323 	    "ibmf_i_rmpp_recvr_term_flow() exit\n");
1324 }
1325 
1326 /*
1327  * ibmf_i_is_valid_rmpp_status():
1328  *	Check for a valid RMPP status
1329  */
1330 static boolean_t
1331 ibmf_i_is_valid_rmpp_status(ibmf_rmpp_hdr_t *rmpp_hdr)
1332 {
1333 	boolean_t	found = B_TRUE;
1334 
1335 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
1336 	    ibmf_i_is_valid_rmpp_status_start, IBMF_TNF_TRACE, "",
1337 	    "ibmf_i_is_valid_rmpp_status(): rmpp_hdr = 0x%p\n",
1338 	    tnf_opaque, rmpp_hdr, rmpp_hdr);
1339 
1340 	if (((rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_DATA) ||
1341 	    (rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_ACK)) &&
1342 	    (rmpp_hdr->rmpp_status != IBMF_RMPP_STATUS_NORMAL))
1343 		found = B_FALSE;
1344 
1345 	if ((rmpp_hdr->rmpp_status == IBMF_RMPP_STATUS_RESX) &&
1346 	    (rmpp_hdr->rmpp_type != IBMF_RMPP_TYPE_STOP))
1347 		found = B_FALSE;
1348 
1349 	if (((rmpp_hdr->rmpp_status == IBMF_RMPP_STATUS_T2L) ||
1350 	    (rmpp_hdr->rmpp_status == IBMF_RMPP_STATUS_ILPL) ||
1351 	    (rmpp_hdr->rmpp_status == IBMF_RMPP_STATUS_IFSN) ||
1352 	    (rmpp_hdr->rmpp_status == IBMF_RMPP_STATUS_BADT) ||
1353 	    (rmpp_hdr->rmpp_status == IBMF_RMPP_STATUS_W2S) ||
1354 	    (rmpp_hdr->rmpp_status == IBMF_RMPP_STATUS_S2B) ||
1355 	    (rmpp_hdr->rmpp_status == IBMF_RMPP_STATUS_IS) ||
1356 	    (rmpp_hdr->rmpp_status == IBMF_RMPP_STATUS_UNV) ||
1357 	    (rmpp_hdr->rmpp_status == IBMF_RMPP_STATUS_TMR) ||
1358 	    (rmpp_hdr->rmpp_status == IBMF_RMPP_STATUS_USP)) &&
1359 	    (rmpp_hdr->rmpp_type != IBMF_RMPP_TYPE_ABORT))
1360 		found = B_FALSE;
1361 
1362 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
1363 	    ibmf_i_is_valid_rmpp_status_end, IBMF_TNF_TRACE, "",
1364 	    "ibmf_i_is_valid_rmpp_status_flow() exit\n");
1365 
1366 	return (found);
1367 }
1368 
1369 /*
1370  * ibmf_i_handle_rmpp():
1371  *	Handle RMPP processing of an incoming IB packet
1372  */
1373 void
1374 ibmf_i_handle_rmpp(ibmf_client_t *clientp, ibmf_qp_handle_t qp_hdl,
1375     ibmf_msg_impl_t *msgimplp, uchar_t *madp)
1376 {
1377 	ibmf_rmpp_ctx_t	*rmpp_ctx = &msgimplp->im_rmpp_ctx;
1378 	ibmf_rmpp_hdr_t *rmpp_hdr;
1379 	int		status;
1380 
1381 	IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4,
1382 	    ibmf_i_handle_rmpp_start, IBMF_TNF_TRACE, "",
1383 	    "ibmf_i_handle_rmpp(): clientp = 0x%p, qp_hdl = 0x%p, "
1384 	    "msgp = 0x%p, madp = 0x%p\n", tnf_opaque, clientp, clientp,
1385 	    tnf_opaque, qp_hdl, qp_hdl, tnf_opaque, msg, msgimplp,
1386 	    tnf_opaque, mad, madp);
1387 
1388 	ASSERT(MUTEX_HELD(&msgimplp->im_mutex));
1389 
1390 	rmpp_hdr = (ibmf_rmpp_hdr_t *)(madp + sizeof (ib_mad_hdr_t));
1391 
1392 	/*
1393 	 * Check the version in the RMPP header
1394 	 */
1395 	if (rmpp_hdr->rmpp_version != IBMF_RMPP_VERSION) {
1396 
1397 		/*
1398 		 * If the receive buffer is not yet allocated, this is
1399 		 * probably the first MAD received for the receive context.
1400 		 * We need to set up the receive buffer before calling
1401 		 * ibmf_i_send_rmpp() to send an ABORT packet.
1402 		 */
1403 		if (msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL) {
1404 			status = ibmf_setup_recvbuf_on_error(msgimplp, madp);
1405 			if (status != IBMF_SUCCESS) {
1406 				IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L2,
1407 				    ibmf_i_handle_rmpp_err, IBMF_TNF_ERROR, "",
1408 				    "ibmf_i_handle_rmpp(): %s\n", tnf_string,
1409 				    msg,
1410 				    "ibmf_setup_recvbuf_on_error() failed");
1411 				return;
1412 			}
1413 		}
1414 
1415 		/*
1416 		 * Drop the message if the transaction has not yet
1417 		 * been identified as a send or receive RMPP transaction.
1418 		 * This is because the send completion of an abort packet
1419 		 * will hit the non-rmpp code which attempts to reset the
1420 		 * RESP timer set after sending the abort packet, causing
1421 		 * an assert.
1422 		 */
1423 		if (((msgimplp->im_flags & IBMF_MSG_FLAGS_RECV_RMPP) == 0) &&
1424 		    (msgimplp->im_flags & IBMF_MSG_FLAGS_SEND_RMPP) == 0) {
1425 			/*
1426 			 * Reset the response timer since we're still
1427 			 * waiting for the first response MAD, provided
1428 			 * that the send completion has occured
1429 			 */
1430 			if (msgimplp->im_trans_state_flags &
1431 			    IBMF_TRANS_STATE_FLAG_SEND_DONE) {
1432 				ibmf_i_set_timer(ibmf_i_send_timeout, msgimplp,
1433 				    IBMF_RESP_TIMER);
1434 			}
1435 
1436 			IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
1437 			    ibmf_i_handle_rmpp, IBMF_TNF_TRACE, "",
1438 			    "ibmf_i_handle_rmpp(): %s\n", tnf_string, msg,
1439 			    "BAD version detected, dropping MAD");
1440 
1441 			return;
1442 		}
1443 
1444 		/* abort with status BadT */
1445 		status = ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ABORT,
1446 		    IBMF_RMPP_STATUS_UNV, 0, 0, IBMF_NO_BLOCK);
1447 		if (status != IBMF_SUCCESS) {
1448 			IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L2,
1449 			    ibmf_i_handle_rmpp_err, IBMF_TNF_ERROR, "",
1450 			    "ibmf_i_handle_rmpp(): %s\n", tnf_string, msg,
1451 			    "RMPP ABORT send failed");
1452 			msgimplp->im_trans_state_flags |=
1453 			    IBMF_TRANS_STATE_FLAG_SEND_DONE;
1454 		}
1455 
1456 		mutex_enter(&clientp->ic_kstat_mutex);
1457 		IBMF_ADD32_KSTATS(clientp, rmpp_errors, 1);
1458 		mutex_exit(&clientp->ic_kstat_mutex);
1459 
1460 		IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
1461 		    ibmf_i_handle_rmpp, IBMF_TNF_TRACE, "",
1462 		    "ibmf_i_handle_rmpp(): %s\n", tnf_string, msg,
1463 		    "Unsupported RMPP version detected, sending ABORT UNV");
1464 
1465 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
1466 		    ibmf_i_handle_rmpp_end, IBMF_TNF_TRACE, "",
1467 		    "ibmf_i_handle_rmpp() exit\n");
1468 
1469 		rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
1470 
1471 		ibmf_i_unset_timer(msgimplp, IBMF_TRANS_TIMER);
1472 
1473 		ibmf_i_set_timer(ibmf_i_err_terminate_timeout,
1474 		    msgimplp, IBMF_RESP_TIMER);
1475 
1476 		return;
1477 	}
1478 
1479 	/*
1480 	 * Check for a valid status in the RMPP header
1481 	 */
1482 	if (ibmf_i_is_valid_rmpp_status(rmpp_hdr) != B_TRUE) {
1483 
1484 		/*
1485 		 * If the receive buffer is not yet allocated, this is
1486 		 * probably the first MAD received for the receive context.
1487 		 * We need to set up the receive buffer before calling
1488 		 * ibmf_i_send_rmpp() to send an ABORT packet.
1489 		 */
1490 		if (msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL) {
1491 			status = ibmf_setup_recvbuf_on_error(msgimplp, madp);
1492 			if (status != IBMF_SUCCESS) {
1493 				IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L2,
1494 				    ibmf_i_handle_rmpp_err, IBMF_TNF_ERROR, "",
1495 				    "ibmf_i_handle_rmpp(): %s\n", tnf_string,
1496 				    msg,
1497 				    "ibmf_setup_recvbuf_on_error() failed");
1498 				return;
1499 			}
1500 		}
1501 
1502 		/*
1503 		 * Drop the message if the transaction has not yet
1504 		 * been identified as a send or receive RMPP transaction.
1505 		 * This is because the send completion of an abort packet
1506 		 * will hit the non-rmpp code which attempts to reset the
1507 		 * RESP timer set after sending the abort packet, causing
1508 		 * an assert.
1509 		 */
1510 		if (((msgimplp->im_flags & IBMF_MSG_FLAGS_RECV_RMPP) == 0) &&
1511 		    (msgimplp->im_flags & IBMF_MSG_FLAGS_SEND_RMPP) == 0) {
1512 			/*
1513 			 * Reset the response timer since we're still
1514 			 * waiting for the first response MAD, provided
1515 			 * that the send completion has occured
1516 			 */
1517 			if (msgimplp->im_trans_state_flags &
1518 			    IBMF_TRANS_STATE_FLAG_SEND_DONE) {
1519 				ibmf_i_set_timer(ibmf_i_send_timeout, msgimplp,
1520 				    IBMF_RESP_TIMER);
1521 			}
1522 
1523 			IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
1524 			    ibmf_i_handle_rmpp, IBMF_TNF_TRACE, "",
1525 			    "ibmf_i_handle_rmpp(): %s\n", tnf_string, msg,
1526 			    "Invalid RMPP status detected, dropping MAD");
1527 
1528 			return;
1529 		}
1530 
1531 		/* abort with status BadT */
1532 		status = ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_ABORT,
1533 		    IBMF_RMPP_STATUS_IS, 0, 0, IBMF_NO_BLOCK);
1534 		if (status != IBMF_SUCCESS) {
1535 			IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L2,
1536 			    ibmf_i_handle_rmpp_err, IBMF_TNF_ERROR, "",
1537 			    "ibmf_i_handle_rmpp(): %s\n", tnf_string, msg,
1538 			    "RMPP ABORT send failed");
1539 			msgimplp->im_trans_state_flags |=
1540 			    IBMF_TRANS_STATE_FLAG_SEND_DONE;
1541 		}
1542 
1543 		mutex_enter(&clientp->ic_kstat_mutex);
1544 		IBMF_ADD32_KSTATS(clientp, rmpp_errors, 1);
1545 		mutex_exit(&clientp->ic_kstat_mutex);
1546 
1547 		IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L2,
1548 		    ibmf_i_handle_rmpp, IBMF_TNF_TRACE, "",
1549 		    "ibmf_i_handle_rmpp(): %s\n", tnf_string, msg,
1550 		    "Invalid RMPP status detected, sending ABORT IS");
1551 
1552 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
1553 		    ibmf_i_handle_rmpp_end, IBMF_TNF_TRACE, "",
1554 		    "ibmf_i_handle_rmpp() exit\n");
1555 
1556 		rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_ABORT;
1557 
1558 		ibmf_i_unset_timer(msgimplp, IBMF_TRANS_TIMER);
1559 
1560 		ibmf_i_set_timer(ibmf_i_err_terminate_timeout,
1561 		    msgimplp, IBMF_RESP_TIMER);
1562 
1563 		return;
1564 	}
1565 
1566 	/*
1567 	 * We could check the MAD here and do an optional abort.
1568 	 * This abort if the MAD header is bad is not required by the spec.
1569 	 * Also, we should account for RRespTime here.
1570 	 */
1571 
1572 	/*
1573 	 * The RMPP engine has four execution flow paths corresponding
1574 	 * to the four states the RMPP state machine can be in at any
1575 	 * given time.  The packet will be dropped if the context is not in any
1576 	 * of these four states.
1577 	 */
1578 	switch (rmpp_ctx->rmpp_state) {
1579 	case IBMF_RMPP_STATE_SENDER_ACTIVE :
1580 		ibmf_i_rmpp_sender_active_flow(clientp, qp_hdl, msgimplp, madp);
1581 		break;
1582 	case IBMF_RMPP_STATE_SENDER_SWITCH :
1583 		ibmf_i_rmpp_sender_switch_flow(clientp, qp_hdl, msgimplp, madp);
1584 		break;
1585 	case IBMF_RMPP_STATE_RECEVR_ACTIVE :
1586 		ibmf_i_rmpp_recvr_active_flow(clientp, qp_hdl, msgimplp, madp);
1587 		break;
1588 	case IBMF_RMPP_STATE_RECEVR_TERMINATE :
1589 		ibmf_i_rmpp_recvr_term_flow(clientp, qp_hdl, msgimplp, madp);
1590 		break;
1591 	default:
1592 		/* Including IBMF_RMPP_STATE_ABORT */
1593 		IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L2,
1594 		    ibmf_i_handle_rmpp, IBMF_TNF_TRACE, "",
1595 		    "ibmf_i_handle_rmpp(): %s, rmpp_state = 0x%x\n",
1596 		    tnf_string, msg, "Dropping packet",
1597 		    tnf_opaque, rmpp_state, rmpp_ctx->rmpp_state);
1598 
1599 		/* Reinitiate the resp timer if the state is ABORT */
1600 		if (rmpp_ctx->rmpp_state == IBMF_RMPP_STATE_ABORT) {
1601 			ibmf_i_set_timer(ibmf_i_err_terminate_timeout, msgimplp,
1602 			    IBMF_RESP_TIMER);
1603 
1604 			return;
1605 		}
1606 
1607 		/*
1608 		 * Drop the message if the transaction has not yet
1609 		 * been identified as a send or receive RMPP transaction.
1610 		 */
1611 		if (((msgimplp->im_flags & IBMF_MSG_FLAGS_RECV_RMPP) == 0) &&
1612 		    (msgimplp->im_flags & IBMF_MSG_FLAGS_SEND_RMPP) == 0) {
1613 			/*
1614 			 * Reset the response timer since we're still
1615 			 * waiting for the first response MAD, provided
1616 			 * that the send completion has occured
1617 			 */
1618 			if (msgimplp->im_trans_state_flags &
1619 			    IBMF_TRANS_STATE_FLAG_SEND_DONE) {
1620 				ibmf_i_set_timer(ibmf_i_send_timeout, msgimplp,
1621 				    IBMF_RESP_TIMER);
1622 			}
1623 
1624 			IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
1625 			    ibmf_i_handle_rmpp, IBMF_TNF_TRACE, "",
1626 			    "ibmf_i_handle_rmpp(): %s\n", tnf_string, msg,
1627 			    "BAD 1st RMPP packet, dropping MAD");
1628 
1629 			return;
1630 		}
1631 	}
1632 
1633 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
1634 	    ibmf_i_handle_rmpp_end, IBMF_TNF_TRACE, "",
1635 	    "ibmf_i_handle_rmpp() exit\n");
1636 }
1637 
1638 /*
1639  * ibmf_i_send_rmpp():
1640  * ibmf_i_send_rmpp() is called to send any
1641  * type RMPP packet. The RMPP status is passed in as an argument.
1642  * In addition, the segment field and the payload length / new window last
1643  * field are passed in as arguments.
1644  */
1645 int
1646 ibmf_i_send_rmpp(ibmf_msg_impl_t *msgimplp, uint8_t rmpp_type,
1647     uint8_t rmpp_status, uint32_t segno, uint32_t nwl, int block)
1648 {
1649 	ibmf_rmpp_ctx_t	*rmpp_ctx = &msgimplp->im_rmpp_ctx;
1650 	int		status;
1651 
1652 	IBMF_TRACE_5(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_send_rmpp_start,
1653 	    IBMF_TNF_TRACE, "",
1654 	    "ibmf_i_send_rmpp(): msgp = 0x%p, rmpp_type = 0x%x, "
1655 	    "rmpp_status = %d, segno = %d, nwl = %d\n",
1656 	    tnf_opaque, msg, msgimplp,
1657 	    tnf_uint, rmpp_type, rmpp_type,
1658 	    tnf_uint, rmpp_status, rmpp_status,
1659 	    tnf_uint, segno, segno,
1660 	    tnf_uint, nwl, nwl);
1661 
1662 	IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_send_rmpp,
1663 	    IBMF_TNF_TRACE, "", "ibmf_i_send_rmpp(): msgp = 0x%p, "
1664 	    "next_seg = 0x%x, num_pkts = %d\n",
1665 	    tnf_opaque, msg, msgimplp,
1666 	    tnf_uint, next_seg, msgimplp->im_rmpp_ctx.rmpp_ns,
1667 	    tnf_uint, num_pkts, msgimplp->im_rmpp_ctx.rmpp_num_pkts);
1668 
1669 	ASSERT(MUTEX_HELD(&msgimplp->im_mutex));
1670 
1671 	rmpp_ctx->rmpp_type = rmpp_type;
1672 	rmpp_ctx->rmpp_status = rmpp_status;
1673 	rmpp_ctx->rmpp_word3 = segno;
1674 	rmpp_ctx->rmpp_word4 = nwl;
1675 
1676 	/*
1677 	 * send packet without blocking
1678 	 */
1679 	status = ibmf_i_send_pkt(msgimplp->im_client, msgimplp->im_qp_hdl,
1680 	    msgimplp, block);
1681 	if (status != IBMF_SUCCESS) {
1682 		IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
1683 		    ibmf_i_send_rmpp_err, IBMF_TNF_ERROR, "",
1684 		    "ibmf_i_send_rmpp(): %s, status = %d\n", tnf_string, msg,
1685 		    "unable to send packet", tnf_uint, status, status);
1686 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,	ibmf_i_send_rmpp_end,
1687 		    IBMF_TNF_TRACE, "", "ibmf_i_send_rmpp() exit\n");
1688 		return (status);
1689 	}
1690 
1691 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,	ibmf_i_send_rmpp_end,
1692 	    IBMF_TNF_TRACE, "", "ibmf_i_send_rmpp() exit\n");
1693 
1694 	return (IBMF_SUCCESS);
1695 }
1696 
1697 /*
1698  * ibmf_i_send_rmpp_window():
1699  *	Send an RMPP protocol window of packets
1700  */
1701 void
1702 ibmf_i_send_rmpp_window(ibmf_msg_impl_t *msgimplp, int block)
1703 {
1704 	ibmf_rmpp_ctx_t	*rmpp_ctx = &msgimplp->im_rmpp_ctx;
1705 	int status, i, numpkts = rmpp_ctx->rmpp_wl - rmpp_ctx->rmpp_ns + 1;
1706 	uint32_t	payload_length, cl_hdr_sz, cl_hdr_off;
1707 
1708 	IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_send_rmpp_window_start,
1709 	    IBMF_TNF_TRACE, "", "ibmf_i_send_rmpp_window(): msgp = 0x%p\n",
1710 	    tnf_opaque, msg, msgimplp);
1711 
1712 	IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_send_rmpp_window,
1713 	    IBMF_TNF_TRACE, "", "ibmf_i_handle_rmpp(): wl = %d "
1714 	    "ns = %d, num_pkts = %d\n", tnf_uint, wl, rmpp_ctx->rmpp_wl,
1715 	    tnf_uint, ns, rmpp_ctx->rmpp_ns, tnf_uint, num_pkts,
1716 	    rmpp_ctx->rmpp_num_pkts);
1717 
1718 	ASSERT(MUTEX_HELD(&msgimplp->im_mutex));
1719 
1720 	ibmf_i_mgt_class_to_hdr_sz_off(
1721 	    msgimplp->im_msgbufs_send.im_bufs_mad_hdr->MgmtClass,
1722 	    &cl_hdr_sz, &cl_hdr_off);
1723 
1724 	for (i = 1; i <= numpkts; i++) {
1725 
1726 		if (rmpp_ctx->rmpp_ns == 1)
1727 			payload_length = rmpp_ctx->rmpp_pyld_len +
1728 			    (rmpp_ctx->rmpp_num_pkts * cl_hdr_sz);
1729 		else if (rmpp_ctx->rmpp_ns == rmpp_ctx->rmpp_num_pkts)
1730 			payload_length = rmpp_ctx->rmpp_last_pkt_sz + cl_hdr_sz;
1731 		else
1732 			payload_length = rmpp_ctx->rmpp_pkt_data_sz;
1733 
1734 		IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_send_rmpp_window,
1735 		    IBMF_TNF_TRACE, "", "ibmf_i_handle_rmpp(): ns = %d, "
1736 		    "pl = %d\n", tnf_uint, ns, rmpp_ctx->rmpp_ns,
1737 		    tnf_uint, pl, payload_length);
1738 
1739 		status = ibmf_i_send_rmpp(msgimplp, IBMF_RMPP_TYPE_DATA,
1740 		    IBMF_RMPP_STATUS_NORMAL, rmpp_ctx->rmpp_ns, payload_length,
1741 		    block);
1742 		if (status != IBMF_SUCCESS) {
1743 
1744 			IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
1745 			    ibmf_i_send_rmpp_window_err, IBMF_TNF_ERROR, "",
1746 			    "ibmf_i_send_rmpp_window(): %s\n", tnf_string, msg,
1747 			    "Send rmpp window failed");
1748 			IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
1749 			    ibmf_i_send_rmpp_window_end, IBMF_TNF_TRACE, "",
1750 			    "ibmf_i_send_rmpp_window() exit\n");
1751 			return;
1752 		}
1753 
1754 		rmpp_ctx->rmpp_ns++;
1755 
1756 		rmpp_ctx->rmpp_data_offset += rmpp_ctx->rmpp_pkt_data_sz;
1757 	}
1758 
1759 	/* Set the response timer */
1760 	IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_send_rmpp_window,
1761 	    IBMF_TNF_TRACE, "", "ibmf_i_handle_rmpp(): setting timer %p %d\n",
1762 	    tnf_opaque, msgimplp, msgimplp, tnf_opaque, timeout_id,
1763 	    msgimplp->im_rp_timeout_id);
1764 
1765 	ibmf_i_set_timer(ibmf_i_send_timeout, msgimplp, IBMF_RESP_TIMER);
1766 
1767 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,	ibmf_i_send_rmpp_window_end,
1768 	    IBMF_TNF_TRACE, "", "ibmf_i_send_rmpp_window() exit\n");
1769 }
1770 
1771 /*
1772  * ibmf_i_send_rmpp_pkts():
1773  *	Send a message using the RMPP protocol
1774  */
1775 int
1776 ibmf_i_send_rmpp_pkts(ibmf_client_t *clientp, ibmf_qp_handle_t ibmf_qp_handle,
1777     ibmf_msg_impl_t *msgimplp, boolean_t isDS, int block)
1778 {
1779 	ibmf_rmpp_ctx_t	*rmpp_ctx = &msgimplp->im_rmpp_ctx;
1780 	size_t		buf_sz = msgimplp->im_msgbufs_send.im_bufs_cl_data_len;
1781 	uint32_t	num_pkts, resid;
1782 	uint32_t	cl_hdr_sz, cl_data_sz, cl_hdr_off;
1783 
1784 	IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_send_rmpp_pkts_start,
1785 	    IBMF_TNF_TRACE, "", "ibmf_i_send_rmpp_pkts(): clientp = 0x%p, "
1786 	    "qphdl = 0x%p, msgp = 0x%p, block = %d\n",
1787 	    tnf_opaque, clientp, clientp, tnf_opaque, qphdl, ibmf_qp_handle,
1788 	    tnf_opaque, msg, msgimplp, tnf_uint, block, block);
1789 
1790 	ASSERT(MUTEX_HELD(&msgimplp->im_mutex));
1791 
1792 	ibmf_i_mgt_class_to_hdr_sz_off(
1793 	    msgimplp->im_msgbufs_send.im_bufs_mad_hdr->MgmtClass,
1794 	    &cl_hdr_sz, &cl_hdr_off);
1795 
1796 	cl_data_sz = MAD_SIZE_IN_BYTES - sizeof (ib_mad_hdr_t) - cl_hdr_off -
1797 	    cl_hdr_sz;
1798 
1799 	if ((resid = (buf_sz % cl_data_sz)) != 0)
1800 		num_pkts = (buf_sz / cl_data_sz) + 1;
1801 	else {
1802 		if (buf_sz > 0)
1803 			num_pkts = buf_sz / cl_data_sz;
1804 		else
1805 			num_pkts = 1;
1806 	}
1807 
1808 	rmpp_ctx->rmpp_wf = 1;
1809 	rmpp_ctx->rmpp_wl = 1;
1810 	rmpp_ctx->rmpp_ns = 1;
1811 	rmpp_ctx->rmpp_is_ds = isDS;
1812 	rmpp_ctx->rmpp_pyld_len = buf_sz;
1813 	rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_SENDER_ACTIVE;
1814 	rmpp_ctx->rmpp_type = IBMF_RMPP_TYPE_DATA;
1815 	rmpp_ctx->rmpp_respt = IBMF_RMPP_TERM_RRESPT;
1816 	rmpp_ctx->rmpp_status = IBMF_RMPP_STATUS_NORMAL;
1817 	rmpp_ctx->rmpp_num_pkts = num_pkts;
1818 	rmpp_ctx->rmpp_pkt_data_sz =
1819 	    (buf_sz < cl_data_sz) ? buf_sz : cl_data_sz;
1820 	rmpp_ctx->rmpp_last_pkt_sz =
1821 	    (resid == 0) ? ((buf_sz == 0) ? 0 : cl_data_sz) : resid;
1822 	rmpp_ctx->rmpp_data_offset = 0;
1823 
1824 	ibmf_i_send_rmpp_window(msgimplp, block);
1825 
1826 	IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,	ibmf_i_send_rmpp_pkts_end,
1827 	    IBMF_TNF_TRACE, "", "ibmf_i_send_rmpp_pkts() exit\n");
1828 
1829 	return (IBMF_SUCCESS);
1830 }
1831