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