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