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