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 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 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 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 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 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 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 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 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 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 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 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