1 /* 2 * Copyright (c) 2005 Topspin Communications. All rights reserved. 3 * Copyright (c) 2005-2006 Intel Corporation. All rights reserved. 4 * 5 * This software is available to you under a choice of one of two 6 * licenses. You may choose to be licensed under the terms of the GNU 7 * General Public License (GPL) Version 2, available from the file 8 * COPYING in the main directory of this source tree, or the 9 * OpenIB.org BSD license below: 10 * 11 * Redistribution and use in source and binary forms, with or 12 * without modification, are permitted provided that the following 13 * conditions are met: 14 * 15 * - Redistributions of source code must retain the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer. 18 * 19 * - Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials 22 * provided with the distribution. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 * SOFTWARE. 32 * 33 * $Id$ 34 */ 35 #define _GNU_SOURCE 36 #include <config.h> 37 38 #include <stdlib.h> 39 #include <string.h> 40 #include <stdio.h> 41 #include <fcntl.h> 42 #include <errno.h> 43 #include <unistd.h> 44 #include <pthread.h> 45 #include <stddef.h> 46 47 #include <infiniband/cm.h> 48 #include <rdma/ib_user_cm.h> 49 #include <infiniband/driver.h> 50 #include <infiniband/marshall.h> 51 52 #define PFX "libibcm: " 53 54 #define IB_USER_CM_MIN_ABI_VERSION 4 55 #define IB_USER_CM_MAX_ABI_VERSION 5 56 57 static int abi_ver; 58 static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; 59 60 enum { 61 IB_UCM_MAX_DEVICES = 32 62 }; 63 64 static inline int ERR(int err) 65 { 66 errno = err; 67 return -1; 68 } 69 70 71 #define CM_CREATE_MSG_CMD_RESP(msg, cmd, resp, type, size) \ 72 do { \ 73 struct ib_ucm_cmd_hdr *hdr; \ 74 \ 75 size = sizeof(*hdr) + sizeof(*cmd); \ 76 msg = alloca(size); \ 77 if (!msg) \ 78 return ERR(ENOMEM); \ 79 hdr = msg; \ 80 cmd = msg + sizeof(*hdr); \ 81 hdr->cmd = type; \ 82 hdr->in = sizeof(*cmd); \ 83 hdr->out = sizeof(*resp); \ 84 memset(cmd, 0, sizeof(*cmd)); \ 85 resp = alloca(sizeof(*resp)); \ 86 if (!resp) \ 87 return ERR(ENOMEM); \ 88 cmd->response = (uintptr_t)resp;\ 89 } while (0) 90 91 #define CM_CREATE_MSG_CMD(msg, cmd, type, size) \ 92 do { \ 93 struct ib_ucm_cmd_hdr *hdr; \ 94 \ 95 size = sizeof(*hdr) + sizeof(*cmd); \ 96 msg = alloca(size); \ 97 if (!msg) \ 98 return ERR(ENOMEM); \ 99 hdr = msg; \ 100 cmd = msg + sizeof(*hdr); \ 101 hdr->cmd = type; \ 102 hdr->in = sizeof(*cmd); \ 103 hdr->out = 0; \ 104 memset(cmd, 0, sizeof(*cmd)); \ 105 } while (0) 106 107 struct cm_id_private { 108 struct ib_cm_id id; 109 int events_completed; 110 pthread_cond_t cond; 111 pthread_mutex_t mut; 112 }; 113 114 static int check_abi_version(void) 115 { 116 char value[8]; 117 118 if (ibv_read_sysfs_file(ibv_get_sysfs_path(), 119 "class/infiniband_cm/abi_version", 120 value, sizeof value) < 0) { 121 fprintf(stderr, PFX "couldn't read ABI version\n"); 122 return 0; 123 } 124 125 abi_ver = strtol(value, NULL, 10); 126 if (abi_ver < IB_USER_CM_MIN_ABI_VERSION || 127 abi_ver > IB_USER_CM_MAX_ABI_VERSION) { 128 fprintf(stderr, PFX "kernel ABI version %d " 129 "doesn't match library version %d.\n", 130 abi_ver, IB_USER_CM_MAX_ABI_VERSION); 131 return -1; 132 } 133 return 0; 134 } 135 136 static int ucm_init(void) 137 { 138 int ret = 0; 139 140 pthread_mutex_lock(&mut); 141 if (!abi_ver) 142 ret = check_abi_version(); 143 pthread_mutex_unlock(&mut); 144 145 return ret; 146 } 147 148 static int ucm_get_dev_index(char *dev_name) 149 { 150 char *dev_path; 151 char ibdev[IBV_SYSFS_NAME_MAX]; 152 int i, ret; 153 154 for (i = 0; i < IB_UCM_MAX_DEVICES; i++) { 155 ret = asprintf(&dev_path, "/sys/class/infiniband_cm/ucm%d", i); 156 if (ret < 0) 157 return -1; 158 159 ret = ibv_read_sysfs_file(dev_path, "ibdev", ibdev, sizeof ibdev); 160 if (ret < 0) 161 continue; 162 163 if (!strcmp(dev_name, ibdev)) { 164 free(dev_path); 165 return i; 166 } 167 168 free(dev_path); 169 } 170 return -1; 171 } 172 173 struct ib_cm_device* ib_cm_open_device(struct ibv_context *device_context) 174 { 175 struct ib_cm_device *dev; 176 char *dev_path; 177 int index, ret; 178 179 if (ucm_init()) 180 return NULL; 181 182 index = ucm_get_dev_index(device_context->device->name); 183 if (index < 0) 184 return NULL; 185 186 dev = malloc(sizeof *dev); 187 if (!dev) 188 return NULL; 189 190 dev->device_context = device_context; 191 192 ret = asprintf(&dev_path, "/dev/ucm%d", index); 193 if (ret < 0) 194 goto err1; 195 196 dev->fd = open(dev_path, O_RDWR); 197 if (dev->fd < 0) 198 goto err2; 199 200 free(dev_path); 201 return dev; 202 203 err2: 204 free(dev_path); 205 err1: 206 free(dev); 207 return NULL; 208 } 209 210 void ib_cm_close_device(struct ib_cm_device *device) 211 { 212 close(device->fd); 213 free(device); 214 } 215 216 static void ib_cm_free_id(struct cm_id_private *cm_id_priv) 217 { 218 pthread_cond_destroy(&cm_id_priv->cond); 219 pthread_mutex_destroy(&cm_id_priv->mut); 220 free(cm_id_priv); 221 } 222 223 static struct cm_id_private *ib_cm_alloc_id(struct ib_cm_device *device, 224 void *context) 225 { 226 struct cm_id_private *cm_id_priv; 227 228 cm_id_priv = malloc(sizeof *cm_id_priv); 229 if (!cm_id_priv) 230 return NULL; 231 232 memset(cm_id_priv, 0, sizeof *cm_id_priv); 233 cm_id_priv->id.device = device; 234 cm_id_priv->id.context = context; 235 pthread_mutex_init(&cm_id_priv->mut, NULL); 236 if (pthread_cond_init(&cm_id_priv->cond, NULL)) 237 goto err; 238 239 return cm_id_priv; 240 241 err: ib_cm_free_id(cm_id_priv); 242 return NULL; 243 } 244 245 int ib_cm_create_id(struct ib_cm_device *device, 246 struct ib_cm_id **cm_id, void *context) 247 { 248 struct ib_ucm_create_id_resp *resp; 249 struct ib_ucm_create_id *cmd; 250 struct cm_id_private *cm_id_priv; 251 void *msg; 252 int result; 253 int size; 254 255 cm_id_priv = ib_cm_alloc_id(device, context); 256 if (!cm_id_priv) 257 return ERR(ENOMEM); 258 259 CM_CREATE_MSG_CMD_RESP(msg, cmd, resp, IB_USER_CM_CMD_CREATE_ID, size); 260 cmd->uid = (uintptr_t) cm_id_priv; 261 262 result = write(device->fd, msg, size); 263 if (result != size) 264 goto err; 265 266 VALGRIND_MAKE_MEM_DEFINED(resp, sizeof *resp); 267 268 cm_id_priv->id.handle = resp->id; 269 *cm_id = &cm_id_priv->id; 270 return 0; 271 272 err: ib_cm_free_id(cm_id_priv); 273 return result; 274 } 275 276 int ib_cm_destroy_id(struct ib_cm_id *cm_id) 277 { 278 struct ib_ucm_destroy_id_resp *resp; 279 struct ib_ucm_destroy_id *cmd; 280 struct cm_id_private *cm_id_priv; 281 void *msg; 282 int result; 283 int size; 284 285 CM_CREATE_MSG_CMD_RESP(msg, cmd, resp, IB_USER_CM_CMD_DESTROY_ID, size); 286 cmd->id = cm_id->handle; 287 288 result = write(cm_id->device->fd, msg, size); 289 if (result != size) 290 return (result >= 0) ? ERR(ENODATA) : -1; 291 292 VALGRIND_MAKE_MEM_DEFINED(resp, sizeof *resp); 293 294 cm_id_priv = container_of(cm_id, struct cm_id_private, id); 295 296 pthread_mutex_lock(&cm_id_priv->mut); 297 while (cm_id_priv->events_completed < resp->events_reported) 298 pthread_cond_wait(&cm_id_priv->cond, &cm_id_priv->mut); 299 pthread_mutex_unlock(&cm_id_priv->mut); 300 301 ib_cm_free_id(cm_id_priv); 302 return 0; 303 } 304 305 int ib_cm_attr_id(struct ib_cm_id *cm_id, struct ib_cm_attr_param *param) 306 { 307 struct ib_ucm_attr_id_resp *resp; 308 struct ib_ucm_attr_id *cmd; 309 void *msg; 310 int result; 311 int size; 312 313 if (!param) 314 return ERR(EINVAL); 315 316 CM_CREATE_MSG_CMD_RESP(msg, cmd, resp, IB_USER_CM_CMD_ATTR_ID, size); 317 cmd->id = cm_id->handle; 318 319 result = write(cm_id->device->fd, msg, size); 320 if (result != size) 321 return (result >= 0) ? ERR(ENODATA) : -1; 322 323 VALGRIND_MAKE_MEM_DEFINED(resp, sizeof *resp); 324 325 param->service_id = resp->service_id; 326 param->service_mask = resp->service_mask; 327 param->local_id = resp->local_id; 328 param->remote_id = resp->remote_id; 329 return 0; 330 } 331 332 int ib_cm_init_qp_attr(struct ib_cm_id *cm_id, 333 struct ibv_qp_attr *qp_attr, 334 int *qp_attr_mask) 335 { 336 struct ibv_kern_qp_attr *resp; 337 struct ib_ucm_init_qp_attr *cmd; 338 void *msg; 339 int result; 340 int size; 341 342 if (!qp_attr || !qp_attr_mask) 343 return ERR(EINVAL); 344 345 CM_CREATE_MSG_CMD_RESP(msg, cmd, resp, IB_USER_CM_CMD_INIT_QP_ATTR, size); 346 cmd->id = cm_id->handle; 347 cmd->qp_state = qp_attr->qp_state; 348 349 result = write(cm_id->device->fd, msg, size); 350 if (result != size) 351 return (result >= 0) ? ERR(ENODATA) : result; 352 353 VALGRIND_MAKE_MEM_DEFINED(resp, sizeof *resp); 354 355 *qp_attr_mask = resp->qp_attr_mask; 356 ibv_copy_qp_attr_from_kern(qp_attr, resp); 357 358 return 0; 359 } 360 361 int ib_cm_listen(struct ib_cm_id *cm_id, 362 __be64 service_id, 363 __be64 service_mask) 364 { 365 struct ib_ucm_listen *cmd; 366 void *msg; 367 int result; 368 int size; 369 370 CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_LISTEN, size); 371 cmd->id = cm_id->handle; 372 cmd->service_id = service_id; 373 cmd->service_mask = service_mask; 374 375 result = write(cm_id->device->fd, msg, size); 376 if (result != size) 377 return (result >= 0) ? ERR(ENODATA) : -1; 378 379 return 0; 380 } 381 382 int ib_cm_send_req(struct ib_cm_id *cm_id, struct ib_cm_req_param *param) 383 { 384 struct ib_user_path_rec p_path; 385 struct ib_user_path_rec *a_path; 386 struct ib_ucm_req *cmd; 387 void *msg; 388 int result; 389 int size; 390 391 if (!param || !param->primary_path) 392 return ERR(EINVAL); 393 394 CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_SEND_REQ, size); 395 cmd->id = cm_id->handle; 396 cmd->qpn = param->qp_num; 397 cmd->qp_type = param->qp_type; 398 cmd->psn = param->starting_psn; 399 cmd->sid = param->service_id; 400 cmd->peer_to_peer = param->peer_to_peer; 401 cmd->responder_resources = param->responder_resources; 402 cmd->initiator_depth = param->initiator_depth; 403 cmd->remote_cm_response_timeout = param->remote_cm_response_timeout; 404 cmd->flow_control = param->flow_control; 405 cmd->local_cm_response_timeout = param->local_cm_response_timeout; 406 cmd->retry_count = param->retry_count; 407 cmd->rnr_retry_count = param->rnr_retry_count; 408 cmd->max_cm_retries = param->max_cm_retries; 409 cmd->srq = param->srq; 410 411 ibv_copy_path_rec_to_kern(&p_path, param->primary_path); 412 cmd->primary_path = (uintptr_t) &p_path; 413 414 if (param->alternate_path) { 415 a_path = alloca(sizeof(*a_path)); 416 if (!a_path) 417 return ERR(ENOMEM); 418 419 ibv_copy_path_rec_to_kern(a_path, param->alternate_path); 420 cmd->alternate_path = (uintptr_t) a_path; 421 } 422 423 if (param->private_data && param->private_data_len) { 424 cmd->data = (uintptr_t) param->private_data; 425 cmd->len = param->private_data_len; 426 } 427 428 result = write(cm_id->device->fd, msg, size); 429 if (result != size) 430 return (result >= 0) ? ERR(ENODATA) : -1; 431 432 return 0; 433 } 434 435 int ib_cm_send_rep(struct ib_cm_id *cm_id, struct ib_cm_rep_param *param) 436 { 437 struct ib_ucm_rep *cmd; 438 void *msg; 439 int result; 440 int size; 441 442 if (!param) 443 return ERR(EINVAL); 444 445 CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_SEND_REP, size); 446 cmd->uid = (uintptr_t) container_of(cm_id, struct cm_id_private, id); 447 cmd->id = cm_id->handle; 448 cmd->qpn = param->qp_num; 449 cmd->psn = param->starting_psn; 450 cmd->responder_resources = param->responder_resources; 451 cmd->initiator_depth = param->initiator_depth; 452 cmd->target_ack_delay = param->target_ack_delay; 453 cmd->failover_accepted = param->failover_accepted; 454 cmd->flow_control = param->flow_control; 455 cmd->rnr_retry_count = param->rnr_retry_count; 456 cmd->srq = param->srq; 457 458 if (param->private_data && param->private_data_len) { 459 cmd->data = (uintptr_t) param->private_data; 460 cmd->len = param->private_data_len; 461 } 462 463 result = write(cm_id->device->fd, msg, size); 464 if (result != size) 465 return (result >= 0) ? ERR(ENODATA) : -1; 466 467 return 0; 468 } 469 470 static inline int cm_send_private_data(struct ib_cm_id *cm_id, 471 uint32_t type, 472 void *private_data, 473 uint8_t private_data_len) 474 { 475 struct ib_ucm_private_data *cmd; 476 void *msg; 477 int result; 478 int size; 479 480 CM_CREATE_MSG_CMD(msg, cmd, type, size); 481 cmd->id = cm_id->handle; 482 483 if (private_data && private_data_len) { 484 cmd->data = (uintptr_t) private_data; 485 cmd->len = private_data_len; 486 } 487 488 result = write(cm_id->device->fd, msg, size); 489 if (result != size) 490 return (result >= 0) ? ERR(ENODATA) : -1; 491 492 return 0; 493 } 494 495 int ib_cm_send_rtu(struct ib_cm_id *cm_id, 496 void *private_data, 497 uint8_t private_data_len) 498 { 499 return cm_send_private_data(cm_id, IB_USER_CM_CMD_SEND_RTU, 500 private_data, private_data_len); 501 } 502 503 int ib_cm_send_dreq(struct ib_cm_id *cm_id, 504 void *private_data, 505 uint8_t private_data_len) 506 { 507 return cm_send_private_data(cm_id, IB_USER_CM_CMD_SEND_DREQ, 508 private_data, private_data_len); 509 } 510 511 int ib_cm_send_drep(struct ib_cm_id *cm_id, 512 void *private_data, 513 uint8_t private_data_len) 514 { 515 return cm_send_private_data(cm_id, IB_USER_CM_CMD_SEND_DREP, 516 private_data, private_data_len); 517 } 518 519 static int cm_establish(struct ib_cm_id *cm_id) 520 { 521 /* In kernel ABI 4 ESTABLISH was repurposed as NOTIFY and gained an 522 extra field. For some reason the compat definitions were deleted 523 from the uapi headers :( */ 524 #define IB_USER_CM_CMD_ESTABLISH IB_USER_CM_CMD_NOTIFY 525 struct cm_abi_establish { /* ABI 4 support */ 526 __u32 id; 527 }; 528 529 struct cm_abi_establish *cmd; 530 void *msg; 531 int result; 532 int size; 533 534 CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_ESTABLISH, size); 535 cmd->id = cm_id->handle; 536 537 result = write(cm_id->device->fd, msg, size); 538 if (result != size) 539 return (result >= 0) ? ERR(ENODATA) : -1; 540 541 return 0; 542 } 543 544 int ib_cm_notify(struct ib_cm_id *cm_id, enum ibv_event_type event) 545 { 546 struct ib_ucm_notify *cmd; 547 void *msg; 548 int result; 549 int size; 550 551 if (abi_ver == 4) { 552 if (event == IBV_EVENT_COMM_EST) 553 return cm_establish(cm_id); 554 else 555 return ERR(EINVAL); 556 } 557 558 CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_NOTIFY, size); 559 cmd->id = cm_id->handle; 560 cmd->event = event; 561 562 result = write(cm_id->device->fd, msg, size); 563 if (result != size) 564 return (result >= 0) ? ERR(ENODATA) : -1; 565 566 return 0; 567 } 568 569 static inline int cm_send_status(struct ib_cm_id *cm_id, 570 uint32_t type, 571 int status, 572 void *info, 573 uint8_t info_length, 574 void *private_data, 575 uint8_t private_data_len) 576 { 577 struct ib_ucm_info *cmd; 578 void *msg; 579 int result; 580 int size; 581 582 CM_CREATE_MSG_CMD(msg, cmd, type, size); 583 cmd->id = cm_id->handle; 584 cmd->status = status; 585 586 if (private_data && private_data_len) { 587 cmd->data = (uintptr_t) private_data; 588 cmd->data_len = private_data_len; 589 } 590 591 if (info && info_length) { 592 cmd->info = (uintptr_t) info; 593 cmd->info_len = info_length; 594 } 595 596 result = write(cm_id->device->fd, msg, size); 597 if (result != size) 598 return (result >= 0) ? ERR(ENODATA) : -1; 599 600 return 0; 601 } 602 603 int ib_cm_send_rej(struct ib_cm_id *cm_id, 604 enum ib_cm_rej_reason reason, 605 void *ari, 606 uint8_t ari_length, 607 void *private_data, 608 uint8_t private_data_len) 609 { 610 return cm_send_status(cm_id, IB_USER_CM_CMD_SEND_REJ, reason, 611 ari, ari_length, 612 private_data, private_data_len); 613 } 614 615 int ib_cm_send_apr(struct ib_cm_id *cm_id, 616 enum ib_cm_apr_status status, 617 void *info, 618 uint8_t info_length, 619 void *private_data, 620 uint8_t private_data_len) 621 { 622 return cm_send_status(cm_id, IB_USER_CM_CMD_SEND_APR, status, 623 info, info_length, 624 private_data, private_data_len); 625 } 626 627 int ib_cm_send_mra(struct ib_cm_id *cm_id, 628 uint8_t service_timeout, 629 void *private_data, 630 uint8_t private_data_len) 631 { 632 struct ib_ucm_mra *cmd; 633 void *msg; 634 int result; 635 int size; 636 637 CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_SEND_MRA, size); 638 cmd->id = cm_id->handle; 639 cmd->timeout = service_timeout; 640 641 if (private_data && private_data_len) { 642 cmd->data = (uintptr_t) private_data; 643 cmd->len = private_data_len; 644 } 645 646 result = write(cm_id->device->fd, msg, size); 647 if (result != size) 648 return (result >= 0) ? ERR(ENODATA) : result; 649 650 return 0; 651 } 652 653 int ib_cm_send_lap(struct ib_cm_id *cm_id, 654 struct ibv_sa_path_rec *alternate_path, 655 void *private_data, 656 uint8_t private_data_len) 657 { 658 struct ib_user_path_rec abi_path; 659 struct ib_ucm_lap *cmd; 660 void *msg; 661 int result; 662 int size; 663 664 CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_SEND_LAP, size); 665 cmd->id = cm_id->handle; 666 667 ibv_copy_path_rec_to_kern(&abi_path, alternate_path); 668 cmd->path = (uintptr_t) &abi_path; 669 670 if (private_data && private_data_len) { 671 cmd->data = (uintptr_t) private_data; 672 cmd->len = private_data_len; 673 } 674 675 result = write(cm_id->device->fd, msg, size); 676 if (result != size) 677 return (result >= 0) ? ERR(ENODATA) : -1; 678 679 return 0; 680 } 681 682 int ib_cm_send_sidr_req(struct ib_cm_id *cm_id, 683 struct ib_cm_sidr_req_param *param) 684 { 685 struct ib_user_path_rec abi_path; 686 struct ib_ucm_sidr_req *cmd; 687 void *msg; 688 int result; 689 int size; 690 691 if (!param || !param->path) 692 return ERR(EINVAL); 693 694 CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_SEND_SIDR_REQ, size); 695 cmd->id = cm_id->handle; 696 cmd->sid = param->service_id; 697 cmd->timeout = param->timeout_ms; 698 cmd->max_cm_retries = param->max_cm_retries; 699 700 ibv_copy_path_rec_to_kern(&abi_path, param->path); 701 cmd->path = (uintptr_t) &abi_path; 702 703 if (param->private_data && param->private_data_len) { 704 cmd->data = (uintptr_t) param->private_data; 705 cmd->len = param->private_data_len; 706 } 707 708 result = write(cm_id->device->fd, msg, size); 709 if (result != size) 710 return (result >= 0) ? ERR(ENODATA) : result; 711 712 return 0; 713 } 714 715 int ib_cm_send_sidr_rep(struct ib_cm_id *cm_id, 716 struct ib_cm_sidr_rep_param *param) 717 { 718 struct ib_ucm_sidr_rep *cmd; 719 void *msg; 720 int result; 721 int size; 722 723 if (!param) 724 return ERR(EINVAL); 725 726 CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_SEND_SIDR_REP, size); 727 cmd->id = cm_id->handle; 728 cmd->qpn = param->qp_num; 729 cmd->qkey = param->qkey; 730 cmd->status = param->status; 731 732 if (param->private_data && param->private_data_len) { 733 cmd->data = (uintptr_t) param->private_data; 734 cmd->data_len = param->private_data_len; 735 } 736 737 if (param->info && param->info_length) { 738 cmd->info = (uintptr_t) param->info; 739 cmd->info_len = param->info_length; 740 } 741 742 result = write(cm_id->device->fd, msg, size); 743 if (result != size) 744 return (result >= 0) ? ERR(ENODATA) : -1; 745 746 return 0; 747 } 748 749 static void cm_event_req_get(struct ib_cm_req_event_param *ureq, 750 struct ib_ucm_req_event_resp *kreq) 751 { 752 ureq->remote_ca_guid = kreq->remote_ca_guid; 753 ureq->remote_qkey = kreq->remote_qkey; 754 ureq->remote_qpn = kreq->remote_qpn; 755 ureq->qp_type = kreq->qp_type; 756 ureq->starting_psn = kreq->starting_psn; 757 ureq->responder_resources = kreq->responder_resources; 758 ureq->initiator_depth = kreq->initiator_depth; 759 ureq->local_cm_response_timeout = kreq->local_cm_response_timeout; 760 ureq->flow_control = kreq->flow_control; 761 ureq->remote_cm_response_timeout = kreq->remote_cm_response_timeout; 762 ureq->retry_count = kreq->retry_count; 763 ureq->rnr_retry_count = kreq->rnr_retry_count; 764 ureq->srq = kreq->srq; 765 ureq->port = kreq->port; 766 767 ibv_copy_path_rec_from_kern(ureq->primary_path, &kreq->primary_path); 768 if (ureq->alternate_path) 769 ibv_copy_path_rec_from_kern(ureq->alternate_path, 770 &kreq->alternate_path); 771 } 772 773 static void cm_event_rep_get(struct ib_cm_rep_event_param *urep, 774 struct ib_ucm_rep_event_resp *krep) 775 { 776 urep->remote_ca_guid = krep->remote_ca_guid; 777 urep->remote_qkey = krep->remote_qkey; 778 urep->remote_qpn = krep->remote_qpn; 779 urep->starting_psn = krep->starting_psn; 780 urep->responder_resources = krep->responder_resources; 781 urep->initiator_depth = krep->initiator_depth; 782 urep->target_ack_delay = krep->target_ack_delay; 783 urep->failover_accepted = krep->failover_accepted; 784 urep->flow_control = krep->flow_control; 785 urep->rnr_retry_count = krep->rnr_retry_count; 786 urep->srq = krep->srq; 787 } 788 789 static void cm_event_sidr_rep_get(struct ib_cm_sidr_rep_event_param *urep, 790 struct ib_ucm_sidr_rep_event_resp *krep) 791 { 792 urep->status = krep->status; 793 urep->qkey = krep->qkey; 794 urep->qpn = krep->qpn; 795 }; 796 797 int ib_cm_get_event(struct ib_cm_device *device, struct ib_cm_event **event) 798 { 799 struct cm_id_private *cm_id_priv; 800 struct ib_ucm_cmd_hdr *hdr; 801 struct ib_ucm_event_get *cmd; 802 struct ib_ucm_event_resp *resp; 803 struct ib_cm_event *evt = NULL; 804 struct ibv_sa_path_rec *path_a = NULL; 805 struct ibv_sa_path_rec *path_b = NULL; 806 void *data = NULL; 807 void *info = NULL; 808 void *msg; 809 int result = 0; 810 int size; 811 812 if (!event) 813 return ERR(EINVAL); 814 815 size = sizeof(*hdr) + sizeof(*cmd); 816 msg = alloca(size); 817 if (!msg) 818 return ERR(ENOMEM); 819 820 hdr = msg; 821 cmd = msg + sizeof(*hdr); 822 823 hdr->cmd = IB_USER_CM_CMD_EVENT; 824 hdr->in = sizeof(*cmd); 825 hdr->out = sizeof(*resp); 826 827 memset(cmd, 0, sizeof(*cmd)); 828 829 resp = alloca(sizeof(*resp)); 830 if (!resp) 831 return ERR(ENOMEM); 832 833 cmd->response = (uintptr_t) resp; 834 cmd->data_len = (uint8_t)(~0U); 835 cmd->info_len = (uint8_t)(~0U); 836 837 data = malloc(cmd->data_len); 838 if (!data) { 839 result = ERR(ENOMEM); 840 goto done; 841 } 842 843 info = malloc(cmd->info_len); 844 if (!info) { 845 result = ERR(ENOMEM); 846 goto done; 847 } 848 849 cmd->data = (uintptr_t) data; 850 cmd->info = (uintptr_t) info; 851 852 result = write(device->fd, msg, size); 853 if (result != size) { 854 result = (result >= 0) ? ERR(ENODATA) : -1; 855 goto done; 856 } 857 858 VALGRIND_MAKE_MEM_DEFINED(resp, sizeof *resp); 859 860 /* 861 * decode event. 862 */ 863 evt = malloc(sizeof(*evt)); 864 if (!evt) { 865 result = ERR(ENOMEM); 866 goto done; 867 } 868 memset(evt, 0, sizeof(*evt)); 869 evt->cm_id = (void *) (uintptr_t) resp->uid; 870 evt->event = resp->event; 871 872 if (resp->present & IB_UCM_PRES_PRIMARY) { 873 path_a = malloc(sizeof(*path_a)); 874 if (!path_a) { 875 result = ERR(ENOMEM); 876 goto done; 877 } 878 } 879 880 if (resp->present & IB_UCM_PRES_ALTERNATE) { 881 path_b = malloc(sizeof(*path_b)); 882 if (!path_b) { 883 result = ERR(ENOMEM); 884 goto done; 885 } 886 } 887 888 switch (evt->event) { 889 case IB_CM_REQ_RECEIVED: 890 evt->param.req_rcvd.listen_id = evt->cm_id; 891 cm_id_priv = ib_cm_alloc_id(evt->cm_id->device, 892 evt->cm_id->context); 893 if (!cm_id_priv) { 894 result = ERR(ENOMEM); 895 goto done; 896 } 897 cm_id_priv->id.handle = resp->id; 898 evt->cm_id = &cm_id_priv->id; 899 evt->param.req_rcvd.primary_path = path_a; 900 evt->param.req_rcvd.alternate_path = path_b; 901 path_a = NULL; 902 path_b = NULL; 903 cm_event_req_get(&evt->param.req_rcvd, &resp->u.req_resp); 904 break; 905 case IB_CM_REP_RECEIVED: 906 cm_event_rep_get(&evt->param.rep_rcvd, &resp->u.rep_resp); 907 break; 908 case IB_CM_MRA_RECEIVED: 909 evt->param.mra_rcvd.service_timeout = resp->u.mra_resp.timeout; 910 break; 911 case IB_CM_REJ_RECEIVED: 912 evt->param.rej_rcvd.reason = resp->u.rej_resp.reason; 913 evt->param.rej_rcvd.ari = info; 914 info = NULL; 915 break; 916 case IB_CM_LAP_RECEIVED: 917 evt->param.lap_rcvd.alternate_path = path_b; 918 path_b = NULL; 919 ibv_copy_path_rec_from_kern(evt->param.lap_rcvd.alternate_path, 920 &resp->u.lap_resp.path); 921 break; 922 case IB_CM_APR_RECEIVED: 923 evt->param.apr_rcvd.ap_status = resp->u.apr_resp.status; 924 evt->param.apr_rcvd.apr_info = info; 925 info = NULL; 926 break; 927 case IB_CM_SIDR_REQ_RECEIVED: 928 evt->param.sidr_req_rcvd.listen_id = evt->cm_id; 929 cm_id_priv = ib_cm_alloc_id(evt->cm_id->device, 930 evt->cm_id->context); 931 if (!cm_id_priv) { 932 result = ERR(ENOMEM); 933 goto done; 934 } 935 cm_id_priv->id.handle = resp->id; 936 evt->cm_id = &cm_id_priv->id; 937 evt->param.sidr_req_rcvd.pkey = resp->u.sidr_req_resp.pkey; 938 evt->param.sidr_req_rcvd.port = resp->u.sidr_req_resp.port; 939 break; 940 case IB_CM_SIDR_REP_RECEIVED: 941 cm_event_sidr_rep_get(&evt->param.sidr_rep_rcvd, 942 &resp->u.sidr_rep_resp); 943 evt->param.sidr_rep_rcvd.info = info; 944 info = NULL; 945 break; 946 default: 947 evt->param.send_status = resp->u.send_status; 948 break; 949 } 950 951 if (resp->present & IB_UCM_PRES_DATA) { 952 evt->private_data = data; 953 data = NULL; 954 } 955 956 *event = evt; 957 evt = NULL; 958 result = 0; 959 done: 960 if (data) 961 free(data); 962 if (info) 963 free(info); 964 if (path_a) 965 free(path_a); 966 if (path_b) 967 free(path_b); 968 if (evt) 969 free(evt); 970 971 return result; 972 } 973 974 int ib_cm_ack_event(struct ib_cm_event *event) 975 { 976 struct cm_id_private *cm_id_priv; 977 978 if (!event) 979 return ERR(EINVAL); 980 981 if (event->private_data) 982 free(event->private_data); 983 984 cm_id_priv = container_of(event->cm_id, struct cm_id_private, id); 985 986 switch (event->event) { 987 case IB_CM_REQ_RECEIVED: 988 cm_id_priv = container_of(event->param.req_rcvd.listen_id, 989 struct cm_id_private, id); 990 free(event->param.req_rcvd.primary_path); 991 if (event->param.req_rcvd.alternate_path) 992 free(event->param.req_rcvd.alternate_path); 993 break; 994 case IB_CM_REJ_RECEIVED: 995 if (event->param.rej_rcvd.ari) 996 free(event->param.rej_rcvd.ari); 997 break; 998 case IB_CM_LAP_RECEIVED: 999 free(event->param.lap_rcvd.alternate_path); 1000 break; 1001 case IB_CM_APR_RECEIVED: 1002 if (event->param.apr_rcvd.apr_info) 1003 free(event->param.apr_rcvd.apr_info); 1004 break; 1005 case IB_CM_SIDR_REQ_RECEIVED: 1006 cm_id_priv = container_of(event->param.sidr_req_rcvd.listen_id, 1007 struct cm_id_private, id); 1008 break; 1009 case IB_CM_SIDR_REP_RECEIVED: 1010 if (event->param.sidr_rep_rcvd.info) 1011 free(event->param.sidr_rep_rcvd.info); 1012 default: 1013 break; 1014 } 1015 1016 pthread_mutex_lock(&cm_id_priv->mut); 1017 cm_id_priv->events_completed++; 1018 pthread_cond_signal(&cm_id_priv->cond); 1019 pthread_mutex_unlock(&cm_id_priv->mut); 1020 1021 free(event); 1022 return 0; 1023 } 1024