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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 /* 26 * Copyright (c) 2005 SilverStorm Technologies, Inc. All rights reserved. 27 * 28 * This software is available to you under a choice of one of two 29 * licenses. You may choose to be licensed under the terms of the GNU 30 * General Public License (GPL) Version 2, available from the file 31 * COPYING in the main directory of this source tree, or the 32 * OpenIB.org BSD license below: 33 * 34 * Redistribution and use in source and binary forms, with or 35 * without modification, are permitted provided that the following 36 * conditions are met: 37 * 38 * - Redistributions of source code must retain the above 39 * copyright notice, this list of conditions and the following 40 * disclaimer. 41 * 42 * - Redistributions in binary form must reproduce the above 43 * copyright notice, this list of conditions and the following 44 * disclaimer in the documentation and/or other materials 45 * provided with the distribution. 46 * 47 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 48 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 49 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 50 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 51 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 52 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 53 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 54 * SOFTWARE. 55 * 56 */ 57 /* 58 * Sun elects to include this software in Sun product 59 * under the OpenIB BSD license. 60 * 61 * 62 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 63 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 64 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 65 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 66 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 67 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 68 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 69 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 70 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 71 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 72 * POSSIBILITY OF SUCH DAMAGE. 73 */ 74 75 #pragma ident "%Z%%M% %I% %E% SMI" 76 77 #include <sys/ib/clients/rds/rdsib_cm.h> 78 #include <sys/ib/clients/rds/rdsib_ib.h> 79 #include <sys/ib/clients/rds/rdsib_buf.h> 80 #include <sys/ib/clients/rds/rdsib_ep.h> 81 82 /* 83 * This file contains CM related work: 84 * 85 * Service registration/deregistration 86 * Path lookup 87 * CM connection callbacks 88 * CM active and passive connection establishment 89 * Connection failover 90 */ 91 92 /* 93 * Handle an incoming CM REQ 94 */ 95 /* ARGSUSED */ 96 static ibt_cm_status_t 97 rds_handle_cm_req(rds_state_t *statep, ibt_cm_event_t *evp, 98 ibt_cm_return_args_t *rargsp, void *rcmp, ibt_priv_data_len_t rcmp_len) 99 { 100 ibt_cm_req_rcv_t *reqp; 101 ib_gid_t lgid, rgid; 102 rds_cm_private_data_t cmp; 103 rds_session_t *sp; 104 rds_ep_t *ep; 105 ibt_channel_hdl_t chanhdl; 106 int ret; 107 108 RDS_DPRINTF2("rds_handle_cm_req", "Enter"); 109 110 reqp = &evp->cm_event.req; 111 rgid = reqp->req_prim_addr.av_dgid; /* requester gid */ 112 lgid = reqp->req_prim_addr.av_sgid; /* receiver gid */ 113 114 RDS_DPRINTF2(LABEL, "REQ Received: From: %llx:%llx To: %llx:%llx", 115 rgid.gid_prefix, rgid.gid_guid, lgid.gid_prefix, lgid.gid_guid); 116 117 /* 118 * CM private data brings IP information 119 * Private data received is a stream of bytes and may not be properly 120 * aligned. So, bcopy the data onto the stack before accessing it. 121 */ 122 bcopy((uint8_t *)evp->cm_priv_data, &cmp, 123 sizeof (rds_cm_private_data_t)); 124 125 RDS_DPRINTF2(LABEL, "REQ Received: From IP: 0x%x To IP: 0x%x type: %d", 126 cmp.cmp_localip, cmp.cmp_remip, cmp.cmp_eptype); 127 128 if (cmp.cmp_version != RDS_VERSION) { 129 RDS_DPRINTF2(LABEL, "Version Mismatch: Local version: %d " 130 "Remote version: %d", RDS_VERSION, cmp.cmp_version); 131 return (IBT_CM_REJECT); 132 } 133 134 if (cmp.cmp_arch != RDS_THIS_ARCH) { 135 RDS_DPRINTF2(LABEL, "ARCH does not match (%d != %d)", 136 cmp.cmp_arch, RDS_THIS_ARCH); 137 return (IBT_CM_REJECT); 138 } 139 140 if ((cmp.cmp_eptype != RDS_EP_TYPE_CTRL) && 141 (cmp.cmp_eptype != RDS_EP_TYPE_DATA)) { 142 RDS_DPRINTF2(LABEL, "Unknown Channel type: %d", cmp.cmp_eptype); 143 return (IBT_CM_REJECT); 144 } 145 146 /* user_buffer_size should be same on all nodes */ 147 if (cmp.cmp_user_buffer_size != UserBufferSize) { 148 RDS_DPRINTF2(LABEL, 149 "UserBufferSize Mismatch, this node: %d remote node: %d", 150 UserBufferSize, cmp.cmp_user_buffer_size); 151 return (IBT_CM_REJECT); 152 } 153 154 /* 155 * RDS needs more time to process a failover REQ so send an MRA. 156 * Otherwise, the remote may retry the REQ and fail the connection. 157 */ 158 if ((cmp.cmp_failover) && (cmp.cmp_eptype == RDS_EP_TYPE_DATA)) { 159 RDS_DPRINTF2("rds_handle_cm_req", "Session Failover, send MRA"); 160 (void) ibt_cm_delay(IBT_CM_DELAY_REQ, evp->cm_session_id, 161 10000000 /* 10 sec */, NULL, 0); 162 } 163 164 /* Is there a session to the destination node? */ 165 rw_enter(&statep->rds_sessionlock, RW_READER); 166 sp = rds_session_lkup(statep, cmp.cmp_localip, rgid.gid_guid); 167 rw_exit(&statep->rds_sessionlock); 168 169 if (sp == NULL) { 170 /* 171 * currently there is no session to the destination 172 * remote ip in the private data is the local ip and vice 173 * versa 174 */ 175 sp = rds_session_create(statep, cmp.cmp_remip, cmp.cmp_localip, 176 reqp, RDS_SESSION_PASSIVE); 177 if (sp == NULL) { 178 /* Check the list anyway. */ 179 rw_enter(&statep->rds_sessionlock, RW_READER); 180 sp = rds_session_lkup(statep, cmp.cmp_localip, 181 rgid.gid_guid); 182 rw_exit(&statep->rds_sessionlock); 183 if (sp == NULL) { 184 /* 185 * The only way this can fail is due to lack 186 * of kernel resources 187 */ 188 return (IBT_CM_REJECT); 189 } 190 } 191 } 192 193 rw_enter(&sp->session_lock, RW_WRITER); 194 195 /* catch peer-to-peer case as soon as possible */ 196 if (sp->session_state == RDS_SESSION_STATE_CREATED) { 197 /* Check possible peer-to-peer case here */ 198 if (sp->session_type != RDS_SESSION_PASSIVE) { 199 RDS_DPRINTF2(LABEL, "SP(%p) Peer-peer connection " 200 "handling", sp); 201 if (lgid.gid_guid > rgid.gid_guid) { 202 /* this node is active so reject this request */ 203 rw_exit(&sp->session_lock); 204 return (IBT_CM_REJECT); 205 } else { 206 /* this node is passive, change the session */ 207 sp->session_type = RDS_SESSION_PASSIVE; 208 sp->session_myip = cmp.cmp_remip; 209 sp->session_lgid = lgid; 210 sp->session_rgid = rgid; 211 } 212 } 213 } 214 215 RDS_DPRINTF2(LABEL, "SP(%p) state: %d", sp, sp->session_state); 216 217 switch (sp->session_state) { 218 case RDS_SESSION_STATE_CONNECTED: 219 RDS_DPRINTF2(LABEL, "STALE Session Detected SP(%p)", sp); 220 sp->session_state = RDS_SESSION_STATE_ERROR; 221 RDS_DPRINTF3("rds_handle_cm_req", "SP(%p) State " 222 "RDS_SESSION_STATE_ERROR", sp); 223 224 /* FALLTHRU */ 225 case RDS_SESSION_STATE_ERROR: 226 case RDS_SESSION_STATE_PASSIVE_CLOSING: 227 sp->session_type = RDS_SESSION_PASSIVE; 228 rw_exit(&sp->session_lock); 229 230 rds_session_close(sp, IBT_NOCALLBACKS, 1); 231 232 /* move the session to init state */ 233 rw_enter(&sp->session_lock, RW_WRITER); 234 ret = rds_session_reinit(sp, lgid); 235 sp->session_myip = cmp.cmp_remip; 236 sp->session_lgid = lgid; 237 sp->session_rgid = rgid; 238 if (ret != 0) { 239 rds_session_fini(sp); 240 sp->session_state = RDS_SESSION_STATE_FAILED; 241 RDS_DPRINTF3("rds_handle_cm_req", "SP(%p) State " 242 "RDS_SESSION_STATE_FAILED", sp); 243 rw_exit(&sp->session_lock); 244 return (IBT_CM_REJECT); 245 } else { 246 sp->session_state = RDS_SESSION_STATE_INIT; 247 RDS_DPRINTF3("rds_handle_cm_req", "SP(%p) State " 248 "RDS_SESSION_STATE_INIT", sp); 249 } 250 251 if (cmp.cmp_eptype == RDS_EP_TYPE_CTRL) { 252 ep = &sp->session_ctrlep; 253 } else { 254 ep = &sp->session_dataep; 255 } 256 break; 257 case RDS_SESSION_STATE_CREATED: 258 case RDS_SESSION_STATE_FAILED: 259 case RDS_SESSION_STATE_FINI: 260 /* 261 * Initialize both channels, we accept this connection 262 * only if both channels are initialized 263 */ 264 sp->session_state = RDS_SESSION_STATE_CREATED; 265 RDS_DPRINTF3("rds_handle_cm_req", "SP(%p) State " 266 "RDS_SESSION_STATE_CREATED", sp); 267 ret = rds_session_init(sp); 268 if (ret != 0) { 269 /* Seems like there are not enough resources */ 270 sp->session_state = RDS_SESSION_STATE_FAILED; 271 RDS_DPRINTF3("rds_handle_cm_req", "SP(%p) State " 272 "RDS_SESSION_STATE_FAILED", sp); 273 rw_exit(&sp->session_lock); 274 return (IBT_CM_REJECT); 275 } 276 sp->session_state = RDS_SESSION_STATE_INIT; 277 RDS_DPRINTF3("rds_handle_cm_req", "SP(%p) State " 278 "RDS_SESSION_STATE_INIT", sp); 279 280 /* FALLTHRU */ 281 case RDS_SESSION_STATE_INIT: 282 if (cmp.cmp_eptype == RDS_EP_TYPE_CTRL) { 283 ep = &sp->session_ctrlep; 284 } else { 285 ep = &sp->session_dataep; 286 } 287 288 break; 289 default: 290 RDS_DPRINTF2(LABEL, "ERROR: SP(%p) is in an unexpected " 291 "state: %d", sp, sp->session_state); 292 rw_exit(&sp->session_lock); 293 return (IBT_CM_REJECT); 294 } 295 296 if (cmp.cmp_failover) { 297 RDS_DPRINTF2("rds_handle_cm_req", 298 "SP(%p) Failover Session (BP %p)", sp, cmp.cmp_last_bufid); 299 sp->session_failover = cmp.cmp_failover; 300 } 301 302 mutex_enter(&ep->ep_lock); 303 if (ep->ep_state == RDS_EP_STATE_UNCONNECTED) { 304 ep->ep_state = RDS_EP_STATE_PASSIVE_PENDING; 305 sp->session_type = RDS_SESSION_PASSIVE; 306 rw_exit(&sp->session_lock); 307 } else if (ep->ep_state == RDS_EP_STATE_ACTIVE_PENDING) { 308 rw_exit(&sp->session_lock); 309 /* 310 * Peer to peer connection. There is an active 311 * connection pending on this ep. The one with 312 * greater port guid becomes active and the 313 * other becomes passive. 314 */ 315 RDS_DPRINTF2(LABEL, "EP(%p) Peer-peer connection handling", ep); 316 if (lgid.gid_guid > rgid.gid_guid) { 317 /* this node is active so reject this request */ 318 mutex_exit(&ep->ep_lock); 319 RDS_DPRINTF2(LABEL, "SP(%p) EP(%p): " 320 "Rejecting passive in favor of active", sp, ep); 321 return (IBT_CM_REJECT); 322 } else { 323 /* 324 * This session is not the active end, change it 325 * to passive end. 326 */ 327 ASSERT(sp->session_type == RDS_SESSION_ACTIVE); 328 ep->ep_state = RDS_EP_STATE_PASSIVE_PENDING; 329 330 rw_enter(&sp->session_lock, RW_WRITER); 331 sp->session_type = RDS_SESSION_PASSIVE; 332 sp->session_lgid = lgid; 333 sp->session_rgid = rgid; 334 rw_exit(&sp->session_lock); 335 } 336 } else { 337 rw_exit(&sp->session_lock); 338 } 339 340 ep->ep_lbufid = cmp.cmp_last_bufid; 341 ep->ep_ackwr.wr.rc.rcwr.rdma.rdma_raddr = (ib_vaddr_t)cmp.cmp_ack_addr; 342 ep->ep_ackwr.wr.rc.rcwr.rdma.rdma_rkey = cmp.cmp_ack_rkey; 343 cmp.cmp_last_bufid = ep->ep_rbufid; 344 cmp.cmp_ack_addr = ep->ep_ack_addr; 345 cmp.cmp_ack_rkey = ep->ep_ack_rkey; 346 mutex_exit(&ep->ep_lock); 347 348 /* continue with accepting the connection request for this channel */ 349 chanhdl = rds_ep_alloc_rc_channel(ep, reqp->req_prim_hca_port); 350 if (chanhdl == NULL) { 351 mutex_enter(&ep->ep_lock); 352 ep->ep_state = RDS_EP_STATE_UNCONNECTED; 353 mutex_exit(&ep->ep_lock); 354 return (IBT_CM_REJECT); 355 } 356 357 /* pre-post recv buffers in the RQ */ 358 rds_post_recv_buf((void *)chanhdl); 359 360 rargsp->cm_ret_len = sizeof (rds_cm_private_data_t); 361 bcopy((uint8_t *)&cmp, rcmp, sizeof (rds_cm_private_data_t)); 362 rargsp->cm_ret.rep.cm_channel = chanhdl; 363 rargsp->cm_ret.rep.cm_rdma_ra_out = 4; 364 rargsp->cm_ret.rep.cm_rdma_ra_in = 4; 365 rargsp->cm_ret.rep.cm_rnr_retry_cnt = MinRnrRetry; 366 367 RDS_DPRINTF2("rds_handle_cm_req", "Return: SP(%p) EP(%p) Chan (%p)", 368 sp, ep, chanhdl); 369 370 return (IBT_CM_ACCEPT); 371 } 372 373 /* 374 * Handle an incoming CM REP 375 * Pre-post recv buffers for the QP 376 */ 377 /* ARGSUSED */ 378 static ibt_cm_status_t 379 rds_handle_cm_rep(ibt_cm_event_t *evp, ibt_cm_return_args_t *rargsp, 380 void *rcmp, ibt_priv_data_len_t rcmp_len) 381 { 382 rds_ep_t *ep; 383 rds_cm_private_data_t cmp; 384 385 RDS_DPRINTF2("rds_handle_cm_rep", "Enter"); 386 387 /* pre-post recv buffers in the RQ */ 388 rds_post_recv_buf((void *)evp->cm_channel); 389 390 ep = (rds_ep_t *)ibt_get_chan_private(evp->cm_channel); 391 bcopy((uint8_t *)evp->cm_priv_data, &cmp, 392 sizeof (rds_cm_private_data_t)); 393 ep->ep_lbufid = cmp.cmp_last_bufid; 394 ep->ep_ackwr.wr.rc.rcwr.rdma.rdma_raddr = (ib_vaddr_t)cmp.cmp_ack_addr; 395 ep->ep_ackwr.wr.rc.rcwr.rdma.rdma_rkey = cmp.cmp_ack_rkey; 396 397 rargsp->cm_ret_len = 0; 398 399 RDS_DPRINTF2("rds_handle_cm_rep", "Return: lbufid: %p", ep->ep_lbufid); 400 401 return (IBT_CM_ACCEPT); 402 } 403 404 /* 405 * Handle CONN EST 406 */ 407 static ibt_cm_status_t 408 rds_handle_cm_conn_est(ibt_cm_event_t *evp) 409 { 410 rds_session_t *sp; 411 rds_ep_t *ep; 412 413 ep = (rds_ep_t *)ibt_get_chan_private(evp->cm_channel); 414 415 RDS_DPRINTF2("rds_handle_cm_conn_est", "EP(%p) State: %d", ep, 416 ep->ep_state); 417 418 mutex_enter(&ep->ep_lock); 419 ASSERT((ep->ep_state == RDS_EP_STATE_ACTIVE_PENDING) || 420 (ep->ep_state == RDS_EP_STATE_PASSIVE_PENDING)); 421 ep->ep_state = RDS_EP_STATE_CONNECTED; 422 ep->ep_chanhdl = evp->cm_channel; 423 sp = ep->ep_sp; 424 mutex_exit(&ep->ep_lock); 425 426 (void) rds_session_active(sp); 427 428 RDS_DPRINTF2("rds_handle_cm_conn_est", "Return"); 429 return (IBT_CM_ACCEPT); 430 } 431 432 /* 433 * Handle CONN CLOSED 434 */ 435 static ibt_cm_status_t 436 rds_handle_cm_conn_closed(ibt_cm_event_t *evp) 437 { 438 rds_ep_t *ep; 439 rds_session_t *sp; 440 441 /* Catch DREQs but ignore DREPs */ 442 if (evp->cm_event.closed != IBT_CM_CLOSED_DREQ_RCVD) { 443 RDS_DPRINTF2("rds_handle_cm_conn_closed", 444 "Ignoring Event: %d received", evp->cm_event.closed); 445 return (IBT_CM_ACCEPT); 446 } 447 448 ep = (rds_ep_t *)ibt_get_chan_private(evp->cm_channel); 449 sp = ep->ep_sp; 450 RDS_DPRINTF2("rds_handle_cm_conn_closed", "EP(%p) Enter", ep); 451 452 mutex_enter(&ep->ep_lock); 453 if (ep->ep_state != RDS_EP_STATE_CONNECTED) { 454 /* Ignore this DREQ */ 455 RDS_DPRINTF2("rds_handle_cm_conn_closed", 456 "EP(%p) not connected, state: %d", ep, ep->ep_state); 457 mutex_exit(&ep->ep_lock); 458 return (IBT_CM_ACCEPT); 459 } 460 ep->ep_state = RDS_EP_STATE_CLOSING; 461 mutex_exit(&ep->ep_lock); 462 463 rw_enter(&sp->session_lock, RW_WRITER); 464 RDS_DPRINTF2("rds_handle_cm_conn_closed", "SP(%p) - state: %d", sp, 465 sp->session_state); 466 467 switch (sp->session_state) { 468 case RDS_SESSION_STATE_CONNECTED: 469 sp->session_state = RDS_SESSION_STATE_PASSIVE_CLOSING; 470 RDS_DPRINTF3("rds_handle_cm_conn_closed", "SP(%p) State " 471 "RDS_SESSION_STATE_PASSIVE_CLOSING", sp); 472 break; 473 474 case RDS_SESSION_STATE_PASSIVE_CLOSING: 475 sp->session_state = RDS_SESSION_STATE_CLOSED; 476 RDS_DPRINTF3("rds_handle_cm_conn_closed", "SP(%p) State " 477 "RDS_SESSION_STATE_CLOSED", sp); 478 rds_passive_session_fini(sp); 479 sp->session_state = RDS_SESSION_STATE_FINI; 480 RDS_DPRINTF3("rds_handle_cm_conn_closed", 481 "SP(%p) State RDS_SESSION_STATE_FINI", sp); 482 break; 483 484 case RDS_SESSION_STATE_ACTIVE_CLOSING: 485 case RDS_SESSION_STATE_ERROR: 486 case RDS_SESSION_STATE_CLOSED: 487 break; 488 489 case RDS_SESSION_STATE_INIT: 490 sp->session_state = RDS_SESSION_STATE_ERROR; 491 RDS_DPRINTF3("rds_handle_cm_conn_closed", "SP(%p) State " 492 "RDS_SESSION_STATE_ERROR", sp); 493 rds_passive_session_fini(sp); 494 sp->session_state = RDS_SESSION_STATE_FAILED; 495 RDS_DPRINTF3("rds_handle_cm_conn_closed", 496 "SP(%p) State RDS_SESSION_STATE_FAILED", sp); 497 break; 498 499 default: 500 RDS_DPRINTF2("rds_handle_cm_conn_closed", 501 "SP(%p) - Unexpected state: %d", sp, sp->session_state); 502 rds_passive_session_fini(sp); 503 sp->session_state = RDS_SESSION_STATE_FAILED; 504 RDS_DPRINTF3("rds_handle_cm_conn_closed", "SP(%p) State " 505 "RDS_SESSION_STATE_FAILED", sp); 506 } 507 rw_exit(&sp->session_lock); 508 509 mutex_enter(&ep->ep_lock); 510 ep->ep_state = RDS_EP_STATE_CLOSED; 511 mutex_exit(&ep->ep_lock); 512 513 RDS_DPRINTF2("rds_handle_cm_conn_closed", "SP(%p) Return", sp); 514 return (IBT_CM_ACCEPT); 515 } 516 517 /* 518 * Handle EVENT FAILURE 519 */ 520 static ibt_cm_status_t 521 rds_handle_cm_event_failure(ibt_cm_event_t *evp) 522 { 523 rds_ep_t *ep; 524 rds_session_t *sp; 525 int ret; 526 527 RDS_DPRINTF2("rds_handle_cm_event_failure", "Enter: Chan hdl: 0x%p " 528 "Code: %d msg: %d reason: %d", evp->cm_channel, 529 evp->cm_event.failed.cf_code, evp->cm_event.failed.cf_msg, 530 evp->cm_event.failed.cf_reason); 531 532 if (evp->cm_channel == NULL) { 533 return (IBT_CM_ACCEPT); 534 } 535 536 ep = (rds_ep_t *)ibt_get_chan_private(evp->cm_channel); 537 sp = ep->ep_sp; 538 539 mutex_enter(&ep->ep_lock); 540 ep->ep_state = RDS_EP_STATE_ERROR; 541 mutex_exit(&ep->ep_lock); 542 543 rw_enter(&sp->session_lock, RW_WRITER); 544 if (sp->session_type == RDS_SESSION_PASSIVE) { 545 RDS_DPRINTF2("rds_handle_cm_event_failure", 546 "SP(%p) - state: %d", sp, sp->session_state); 547 if ((sp->session_state == RDS_SESSION_STATE_INIT) || 548 (sp->session_state == RDS_SESSION_STATE_CONNECTED)) { 549 sp->session_state = RDS_SESSION_STATE_ERROR; 550 RDS_DPRINTF3("rds_handle_cm_event_failure", 551 "SP(%p) State RDS_SESSION_STATE_ERROR", sp); 552 553 /* 554 * Store the cm_channel for freeing later 555 * Active side frees it on ibt_open_rc_channel 556 * failure 557 */ 558 if (ep->ep_chanhdl == NULL) { 559 ep->ep_chanhdl = evp->cm_channel; 560 } 561 rw_exit(&sp->session_lock); 562 563 /* 564 * rds_passive_session_fini should not be called 565 * directly in the CM handler. It will cause a deadlock. 566 */ 567 ret = ddi_taskq_dispatch(rds_taskq, 568 rds_cleanup_passive_session, (void *)sp, 569 DDI_NOSLEEP); 570 if (ret != DDI_SUCCESS) { 571 RDS_DPRINTF1("rds_handle_cm_event_failure", 572 "SP(%p) TaskQ dispatch FAILED:%d", sp, ret); 573 } 574 return (IBT_CM_ACCEPT); 575 } 576 } 577 rw_exit(&sp->session_lock); 578 579 RDS_DPRINTF2("rds_handle_cm_event_failure", "SP(%p) Return", sp); 580 return (IBT_CM_ACCEPT); 581 } 582 583 /* 584 * CM Handler 585 * 586 * Called by IBCM 587 * The cm_private type differs for active and passive events. 588 */ 589 ibt_cm_status_t 590 rds_cm_handler(void *cm_private, ibt_cm_event_t *eventp, 591 ibt_cm_return_args_t *ret_args, void *ret_priv_data, 592 ibt_priv_data_len_t ret_len_max) 593 { 594 ibt_cm_status_t ret = IBT_CM_ACCEPT; 595 596 RDS_DPRINTF2("rds_cm_handler", "Enter: event: %d", eventp->cm_type); 597 598 switch (eventp->cm_type) { 599 case IBT_CM_EVENT_REQ_RCV: 600 ret = rds_handle_cm_req((rds_state_t *)cm_private, eventp, 601 ret_args, ret_priv_data, ret_len_max); 602 break; 603 case IBT_CM_EVENT_REP_RCV: 604 ret = rds_handle_cm_rep(eventp, ret_args, ret_priv_data, 605 ret_len_max); 606 break; 607 case IBT_CM_EVENT_MRA_RCV: 608 /* Not supported */ 609 break; 610 case IBT_CM_EVENT_CONN_EST: 611 ret = rds_handle_cm_conn_est(eventp); 612 break; 613 case IBT_CM_EVENT_CONN_CLOSED: 614 ret = rds_handle_cm_conn_closed(eventp); 615 break; 616 case IBT_CM_EVENT_FAILURE: 617 ret = rds_handle_cm_event_failure(eventp); 618 break; 619 case IBT_CM_EVENT_LAP_RCV: 620 /* Not supported */ 621 RDS_DPRINTF2(LABEL, "LAP message received"); 622 break; 623 case IBT_CM_EVENT_APR_RCV: 624 /* Not supported */ 625 RDS_DPRINTF2(LABEL, "APR message received"); 626 break; 627 default: 628 break; 629 } 630 631 RDS_DPRINTF2("rds_cm_handler", "Return"); 632 633 return (ret); 634 } 635 636 /* 637 * Register the wellknown service with service id: RDS_SERVICE_ID 638 * Incoming connection requests should arrive on this service id. 639 */ 640 ibt_srv_hdl_t 641 rds_register_service(ibt_clnt_hdl_t rds_ibhdl) 642 { 643 ibt_srv_hdl_t srvhdl; 644 ibt_srv_desc_t srvdesc; 645 int ret; 646 647 RDS_DPRINTF2("rds_register_service", "Enter: 0x%p", rds_ibhdl); 648 649 bzero(&srvdesc, sizeof (ibt_srv_desc_t)); 650 srvdesc.sd_handler = rds_cm_handler; 651 srvdesc.sd_flags = IBT_SRV_NO_FLAGS; 652 653 ret = ibt_register_service(rds_ibhdl, &srvdesc, RDS_SERVICE_ID, 654 1, &srvhdl, NULL); 655 if (ret != IBT_SUCCESS) { 656 RDS_DPRINTF2(LABEL, "RDS Service Registration Failed: %d", 657 ret); 658 return (NULL); 659 } 660 661 RDS_DPRINTF2("rds_register_service", "Return: 0x%p", srvhdl); 662 return (srvhdl); 663 } 664 665 /* Bind the RDS service on all ports */ 666 int 667 rds_bind_service(rds_state_t *statep) 668 { 669 rds_hca_t *hcap; 670 ib_gid_t gid; 671 uint_t jx, nbinds = 0, nports = 0; 672 int ret; 673 674 RDS_DPRINTF2("rds_bind_service", "Enter: 0x%p", statep); 675 676 hcap = statep->rds_hcalistp; 677 while (hcap != NULL) { 678 for (jx = 0; jx < hcap->hca_nports; jx++) { 679 nports++; 680 if (hcap->hca_pinfop[jx].p_linkstate != 681 IBT_PORT_ACTIVE) { 682 /* 683 * service bind will be called in the async 684 * handler when the port comes up 685 */ 686 continue; 687 } 688 689 gid = hcap->hca_pinfop[jx].p_sgid_tbl[0]; 690 RDS_DPRINTF5(LABEL, "HCA: 0x%llx Port: %d " 691 "gid: %llx:%llx", hcap->hca_guid, 692 hcap->hca_pinfop[jx].p_port_num, gid.gid_prefix, 693 gid.gid_guid); 694 695 /* pass statep as cm_private */ 696 ret = ibt_bind_service(statep->rds_srvhdl, gid, 697 NULL, statep, NULL); 698 if (ret != IBT_SUCCESS) { 699 RDS_DPRINTF2(LABEL, "Bind service for " 700 "HCA: 0x%llx Port: %d gid %llx:%llx " 701 "failed: %d", hcap->hca_guid, 702 hcap->hca_pinfop[jx].p_port_num, 703 gid.gid_prefix, gid.gid_guid, ret); 704 continue; 705 } 706 707 nbinds++; 708 } 709 hcap = hcap->hca_nextp; 710 } 711 712 RDS_DPRINTF2(LABEL, "RDS Service available on %d/%d ports", 713 nbinds, nports); 714 715 #if 0 716 if (nbinds == 0) { 717 return (-1); 718 } 719 #endif 720 721 RDS_DPRINTF2("rds_bind_service", "Return"); 722 723 return (0); 724 } 725 726 /* Open an RC connection */ 727 int 728 rds_open_rc_channel(rds_ep_t *ep, ibt_path_info_t *pinfo, 729 ibt_execution_mode_t mode, ibt_channel_hdl_t *chanhdl) 730 { 731 rds_session_t *sp; 732 ibt_chan_open_args_t ocargs; 733 ibt_rc_returns_t ocrets; 734 rds_cm_private_data_t cmp; 735 uint8_t hca_port; 736 ibt_channel_hdl_t hdl; 737 int ret = 0; 738 739 RDS_DPRINTF2("rds_open_rc_channel", "Enter: EP(%p) mode: %d", ep, mode); 740 741 sp = ep->ep_sp; 742 743 hca_port = pinfo->pi_prim_cep_path.cep_hca_port_num; 744 745 hdl = rds_ep_alloc_rc_channel(ep, hca_port); 746 if (hdl == NULL) { 747 return (-1); 748 } 749 750 cmp.cmp_version = RDS_VERSION; 751 cmp.cmp_arch = RDS_THIS_ARCH; 752 cmp.cmp_remip = sp->session_remip; 753 cmp.cmp_localip = sp->session_myip; 754 cmp.cmp_eptype = ep->ep_type; 755 cmp.cmp_failover = sp->session_failover; 756 cmp.cmp_last_bufid = ep->ep_rbufid; 757 cmp.cmp_user_buffer_size = UserBufferSize; 758 cmp.cmp_ack_addr = ep->ep_ack_addr; 759 cmp.cmp_ack_rkey = ep->ep_ack_rkey; 760 761 bzero(&ocargs, sizeof (ibt_chan_open_args_t)); 762 bzero(&ocrets, sizeof (ibt_rc_returns_t)); 763 ocargs.oc_path = pinfo; 764 ocargs.oc_cm_handler = rds_cm_handler; 765 ocargs.oc_cm_clnt_private = NULL; 766 ocargs.oc_rdma_ra_out = 4; 767 ocargs.oc_rdma_ra_in = 4; 768 ocargs.oc_priv_data_len = sizeof (rds_cm_private_data_t); 769 ocargs.oc_priv_data = &cmp; 770 ocargs.oc_path_retry_cnt = IBPathRetryCount; 771 ocargs.oc_path_rnr_retry_cnt = MinRnrRetry; 772 ret = ibt_open_rc_channel(hdl, IBT_OCHAN_NO_FLAGS, 773 mode, &ocargs, &ocrets); 774 if (ret != IBT_SUCCESS) { 775 RDS_DPRINTF2(LABEL, "SP(%p) EP(%p) ibt_open_rc_channel " 776 "failed: %d", sp, ep, ret); 777 (void) ibt_flush_channel(hdl); 778 (void) ibt_free_channel(hdl); 779 /* cleanup stuff allocated in rds_ep_alloc_rc_channel */ 780 (void) ibt_free_cq(ep->ep_recvcq); 781 ep->ep_recvcq = NULL; 782 (void) ibt_free_cq(ep->ep_sendcq); 783 ep->ep_sendcq = NULL; 784 return (-1); 785 } 786 787 *chanhdl = hdl; 788 789 RDS_DPRINTF2("rds_open_rc_channel", "Return: EP(%p) Chan: %p", ep, 790 *chanhdl); 791 792 return (0); 793 } 794 795 int 796 rds_close_rc_channel(ibt_channel_hdl_t chanhdl, ibt_execution_mode_t mode) 797 { 798 int ret; 799 800 RDS_DPRINTF2("rds_close_rc_channel", "Enter: Chan(%p) Mode(%d)", 801 chanhdl, mode); 802 803 ret = ibt_close_rc_channel(chanhdl, mode, NULL, 0, NULL, NULL, 0); 804 805 RDS_DPRINTF2("rds_close_rc_channel", "Return Chan(%p)", chanhdl); 806 807 return (ret); 808 } 809