1219820Sjeff/* 2219820Sjeff * Copyright (c) 2005 Topspin Communications. All rights reserved. 3219820Sjeff * Copyright (c) 2005-2006 Intel Corporation. All rights reserved. 4219820Sjeff * 5219820Sjeff * This software is available to you under a choice of one of two 6219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 7219820Sjeff * General Public License (GPL) Version 2, available from the file 8219820Sjeff * COPYING in the main directory of this source tree, or the 9219820Sjeff * OpenIB.org BSD license below: 10219820Sjeff * 11219820Sjeff * Redistribution and use in source and binary forms, with or 12219820Sjeff * without modification, are permitted provided that the following 13219820Sjeff * conditions are met: 14219820Sjeff * 15219820Sjeff * - Redistributions of source code must retain the above 16219820Sjeff * copyright notice, this list of conditions and the following 17219820Sjeff * disclaimer. 18219820Sjeff * 19219820Sjeff * - Redistributions in binary form must reproduce the above 20219820Sjeff * copyright notice, this list of conditions and the following 21219820Sjeff * disclaimer in the documentation and/or other materials 22219820Sjeff * provided with the distribution. 23219820Sjeff * 24219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31219820Sjeff * SOFTWARE. 32219820Sjeff * 33219820Sjeff * $Id$ 34219820Sjeff */ 35219820Sjeff 36219820Sjeff#if HAVE_CONFIG_H 37219820Sjeff# include <config.h> 38219820Sjeff#endif /* HAVE_CONFIG_H */ 39219820Sjeff 40219820Sjeff#include <stdlib.h> 41219820Sjeff#include <string.h> 42219820Sjeff#include <stdio.h> 43219820Sjeff#include <fcntl.h> 44219820Sjeff#include <errno.h> 45219820Sjeff#include <unistd.h> 46219820Sjeff#include <pthread.h> 47219820Sjeff#include <stddef.h> 48219820Sjeff 49219820Sjeff#include <infiniband/cm.h> 50219820Sjeff#include <infiniband/cm_abi.h> 51219820Sjeff#include <infiniband/driver.h> 52219820Sjeff#include <infiniband/marshall.h> 53219820Sjeff 54219820Sjeff#ifdef INCLUDE_VALGRIND 55219820Sjeff# include <valgrind/memcheck.h> 56219820Sjeff# ifndef VALGRIND_MAKE_MEM_DEFINED 57219820Sjeff# warning "Valgrind requested, but VALGRIND_MAKE_MEM_DEFINED undefined" 58219820Sjeff# endif 59219820Sjeff#endif 60219820Sjeff 61219820Sjeff#ifndef VALGRIND_MAKE_MEM_DEFINED 62219820Sjeff# define VALGRIND_MAKE_MEM_DEFINED(addr,len) 63219820Sjeff#endif 64219820Sjeff 65219820Sjeff#define PFX "libibcm: " 66219820Sjeff 67219820Sjeffstatic int abi_ver; 68219820Sjeffstatic pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; 69219820Sjeff 70219820Sjeffenum { 71219820Sjeff IB_UCM_MAX_DEVICES = 32 72219820Sjeff}; 73219820Sjeff 74219820Sjeffstatic inline int ERR(int err) 75219820Sjeff{ 76219820Sjeff errno = err; 77219820Sjeff return -1; 78219820Sjeff} 79219820Sjeff 80219820Sjeff 81219820Sjeff#define CM_CREATE_MSG_CMD_RESP(msg, cmd, resp, type, size) \ 82219820Sjeffdo { \ 83219820Sjeff struct cm_abi_cmd_hdr *hdr; \ 84219820Sjeff \ 85219820Sjeff size = sizeof(*hdr) + sizeof(*cmd); \ 86219820Sjeff msg = alloca(size); \ 87219820Sjeff if (!msg) \ 88219820Sjeff return ERR(ENOMEM); \ 89219820Sjeff hdr = msg; \ 90219820Sjeff cmd = msg + sizeof(*hdr); \ 91219820Sjeff hdr->cmd = type; \ 92219820Sjeff hdr->in = sizeof(*cmd); \ 93219820Sjeff hdr->out = sizeof(*resp); \ 94219820Sjeff memset(cmd, 0, sizeof(*cmd)); \ 95219820Sjeff resp = alloca(sizeof(*resp)); \ 96219820Sjeff if (!resp) \ 97219820Sjeff return ERR(ENOMEM); \ 98219820Sjeff cmd->response = (uintptr_t)resp;\ 99219820Sjeff} while (0) 100219820Sjeff 101219820Sjeff#define CM_CREATE_MSG_CMD(msg, cmd, type, size) \ 102219820Sjeffdo { \ 103219820Sjeff struct cm_abi_cmd_hdr *hdr; \ 104219820Sjeff \ 105219820Sjeff size = sizeof(*hdr) + sizeof(*cmd); \ 106219820Sjeff msg = alloca(size); \ 107219820Sjeff if (!msg) \ 108219820Sjeff return ERR(ENOMEM); \ 109219820Sjeff hdr = msg; \ 110219820Sjeff cmd = msg + sizeof(*hdr); \ 111219820Sjeff hdr->cmd = type; \ 112219820Sjeff hdr->in = sizeof(*cmd); \ 113219820Sjeff hdr->out = 0; \ 114219820Sjeff memset(cmd, 0, sizeof(*cmd)); \ 115219820Sjeff} while (0) 116219820Sjeff 117219820Sjeffstruct cm_id_private { 118219820Sjeff struct ib_cm_id id; 119219820Sjeff int events_completed; 120219820Sjeff pthread_cond_t cond; 121219820Sjeff pthread_mutex_t mut; 122219820Sjeff}; 123219820Sjeff 124219820Sjeff#define container_of(ptr, type, field) \ 125219820Sjeff ((type *) ((void *)ptr - offsetof(type, field))) 126219820Sjeff 127219820Sjeffstatic int check_abi_version(void) 128219820Sjeff{ 129219820Sjeff char value[8]; 130219820Sjeff 131219820Sjeff if (ibv_read_sysfs_file(ibv_get_sysfs_path(), 132219820Sjeff "class/infiniband_cm/abi_version", 133219820Sjeff value, sizeof value) < 0) { 134219820Sjeff fprintf(stderr, PFX "couldn't read ABI version\n"); 135219820Sjeff return 0; 136219820Sjeff } 137219820Sjeff 138219820Sjeff abi_ver = strtol(value, NULL, 10); 139219820Sjeff if (abi_ver < IB_USER_CM_MIN_ABI_VERSION || 140219820Sjeff abi_ver > IB_USER_CM_MAX_ABI_VERSION) { 141219820Sjeff fprintf(stderr, PFX "kernel ABI version %d " 142219820Sjeff "doesn't match library version %d.\n", 143219820Sjeff abi_ver, IB_USER_CM_MAX_ABI_VERSION); 144219820Sjeff return -1; 145219820Sjeff } 146219820Sjeff return 0; 147219820Sjeff} 148219820Sjeff 149219820Sjeffstatic int ucm_init(void) 150219820Sjeff{ 151219820Sjeff int ret = 0; 152219820Sjeff 153219820Sjeff pthread_mutex_lock(&mut); 154219820Sjeff if (!abi_ver) 155219820Sjeff ret = check_abi_version(); 156219820Sjeff pthread_mutex_unlock(&mut); 157219820Sjeff 158219820Sjeff return ret; 159219820Sjeff} 160219820Sjeff 161219820Sjeffstatic int ucm_get_dev_index(char *dev_name) 162219820Sjeff{ 163219820Sjeff char *dev_path; 164219820Sjeff char ibdev[IBV_SYSFS_NAME_MAX]; 165219820Sjeff int i, ret; 166219820Sjeff 167219820Sjeff for (i = 0; i < IB_UCM_MAX_DEVICES; i++) { 168219820Sjeff ret = asprintf(&dev_path, "/sys/class/infiniband_cm/ucm%d", i); 169219820Sjeff if (ret < 0) 170219820Sjeff return -1; 171219820Sjeff 172219820Sjeff ret = ibv_read_sysfs_file(dev_path, "ibdev", ibdev, sizeof ibdev); 173219820Sjeff if (ret < 0) 174219820Sjeff continue; 175219820Sjeff 176219820Sjeff if (!strcmp(dev_name, ibdev)) { 177219820Sjeff free(dev_path); 178219820Sjeff return i; 179219820Sjeff } 180219820Sjeff 181219820Sjeff free(dev_path); 182219820Sjeff } 183219820Sjeff return -1; 184219820Sjeff} 185219820Sjeff 186219820Sjeffstruct ib_cm_device* ib_cm_open_device(struct ibv_context *device_context) 187219820Sjeff{ 188219820Sjeff struct ib_cm_device *dev; 189219820Sjeff char *dev_path; 190219820Sjeff int index, ret; 191219820Sjeff 192219820Sjeff if (ucm_init()) 193219820Sjeff return NULL; 194219820Sjeff 195219820Sjeff index = ucm_get_dev_index(device_context->device->name); 196219820Sjeff if (index < 0) 197219820Sjeff return NULL; 198219820Sjeff 199219820Sjeff dev = malloc(sizeof *dev); 200219820Sjeff if (!dev) 201219820Sjeff return NULL; 202219820Sjeff 203219820Sjeff dev->device_context = device_context; 204219820Sjeff 205219820Sjeff ret = asprintf(&dev_path, "/dev/infiniband/ucm%d", index); 206219820Sjeff if (ret < 0) 207219820Sjeff goto err1; 208219820Sjeff 209219820Sjeff dev->fd = open(dev_path, O_RDWR); 210219820Sjeff if (dev->fd < 0) 211219820Sjeff goto err2; 212219820Sjeff 213219820Sjeff free(dev_path); 214219820Sjeff return dev; 215219820Sjeff 216219820Sjefferr2: 217219820Sjeff free(dev_path); 218219820Sjefferr1: 219219820Sjeff free(dev); 220219820Sjeff return NULL; 221219820Sjeff} 222219820Sjeff 223219820Sjeffvoid ib_cm_close_device(struct ib_cm_device *device) 224219820Sjeff{ 225219820Sjeff close(device->fd); 226219820Sjeff free(device); 227219820Sjeff} 228219820Sjeff 229219820Sjeffstatic void ib_cm_free_id(struct cm_id_private *cm_id_priv) 230219820Sjeff{ 231219820Sjeff pthread_cond_destroy(&cm_id_priv->cond); 232219820Sjeff pthread_mutex_destroy(&cm_id_priv->mut); 233219820Sjeff free(cm_id_priv); 234219820Sjeff} 235219820Sjeff 236219820Sjeffstatic struct cm_id_private *ib_cm_alloc_id(struct ib_cm_device *device, 237219820Sjeff void *context) 238219820Sjeff{ 239219820Sjeff struct cm_id_private *cm_id_priv; 240219820Sjeff 241219820Sjeff cm_id_priv = malloc(sizeof *cm_id_priv); 242219820Sjeff if (!cm_id_priv) 243219820Sjeff return NULL; 244219820Sjeff 245219820Sjeff memset(cm_id_priv, 0, sizeof *cm_id_priv); 246219820Sjeff cm_id_priv->id.device = device; 247219820Sjeff cm_id_priv->id.context = context; 248219820Sjeff pthread_mutex_init(&cm_id_priv->mut, NULL); 249219820Sjeff if (pthread_cond_init(&cm_id_priv->cond, NULL)) 250219820Sjeff goto err; 251219820Sjeff 252219820Sjeff return cm_id_priv; 253219820Sjeff 254219820Sjefferr: ib_cm_free_id(cm_id_priv); 255219820Sjeff return NULL; 256219820Sjeff} 257219820Sjeff 258219820Sjeffint ib_cm_create_id(struct ib_cm_device *device, 259219820Sjeff struct ib_cm_id **cm_id, void *context) 260219820Sjeff{ 261219820Sjeff struct cm_abi_create_id_resp *resp; 262219820Sjeff struct cm_abi_create_id *cmd; 263219820Sjeff struct cm_id_private *cm_id_priv; 264219820Sjeff void *msg; 265219820Sjeff int result; 266219820Sjeff int size; 267219820Sjeff 268219820Sjeff cm_id_priv = ib_cm_alloc_id(device, context); 269219820Sjeff if (!cm_id_priv) 270219820Sjeff return ERR(ENOMEM); 271219820Sjeff 272219820Sjeff CM_CREATE_MSG_CMD_RESP(msg, cmd, resp, IB_USER_CM_CMD_CREATE_ID, size); 273219820Sjeff cmd->uid = (uintptr_t) cm_id_priv; 274219820Sjeff 275219820Sjeff result = write(device->fd, msg, size); 276219820Sjeff if (result != size) 277219820Sjeff goto err; 278219820Sjeff 279219820Sjeff VALGRIND_MAKE_MEM_DEFINED(resp, sizeof *resp); 280219820Sjeff 281219820Sjeff cm_id_priv->id.handle = resp->id; 282219820Sjeff *cm_id = &cm_id_priv->id; 283219820Sjeff return 0; 284219820Sjeff 285219820Sjefferr: ib_cm_free_id(cm_id_priv); 286219820Sjeff return result; 287219820Sjeff} 288219820Sjeff 289219820Sjeffint ib_cm_destroy_id(struct ib_cm_id *cm_id) 290219820Sjeff{ 291219820Sjeff struct cm_abi_destroy_id_resp *resp; 292219820Sjeff struct cm_abi_destroy_id *cmd; 293219820Sjeff struct cm_id_private *cm_id_priv; 294219820Sjeff void *msg; 295219820Sjeff int result; 296219820Sjeff int size; 297219820Sjeff 298219820Sjeff CM_CREATE_MSG_CMD_RESP(msg, cmd, resp, IB_USER_CM_CMD_DESTROY_ID, size); 299219820Sjeff cmd->id = cm_id->handle; 300219820Sjeff 301219820Sjeff result = write(cm_id->device->fd, msg, size); 302219820Sjeff if (result != size) 303219820Sjeff return (result >= 0) ? ERR(ECONNREFUSED) : -1; 304219820Sjeff 305219820Sjeff VALGRIND_MAKE_MEM_DEFINED(resp, sizeof *resp); 306219820Sjeff 307219820Sjeff cm_id_priv = container_of(cm_id, struct cm_id_private, id); 308219820Sjeff 309219820Sjeff pthread_mutex_lock(&cm_id_priv->mut); 310219820Sjeff while (cm_id_priv->events_completed < resp->events_reported) 311219820Sjeff pthread_cond_wait(&cm_id_priv->cond, &cm_id_priv->mut); 312219820Sjeff pthread_mutex_unlock(&cm_id_priv->mut); 313219820Sjeff 314219820Sjeff ib_cm_free_id(cm_id_priv); 315219820Sjeff return 0; 316219820Sjeff} 317219820Sjeff 318219820Sjeffint ib_cm_attr_id(struct ib_cm_id *cm_id, struct ib_cm_attr_param *param) 319219820Sjeff{ 320219820Sjeff struct cm_abi_attr_id_resp *resp; 321219820Sjeff struct cm_abi_attr_id *cmd; 322219820Sjeff void *msg; 323219820Sjeff int result; 324219820Sjeff int size; 325219820Sjeff 326219820Sjeff if (!param) 327219820Sjeff return ERR(EINVAL); 328219820Sjeff 329219820Sjeff CM_CREATE_MSG_CMD_RESP(msg, cmd, resp, IB_USER_CM_CMD_ATTR_ID, size); 330219820Sjeff cmd->id = cm_id->handle; 331219820Sjeff 332219820Sjeff result = write(cm_id->device->fd, msg, size); 333219820Sjeff if (result != size) 334219820Sjeff return (result >= 0) ? ERR(ECONNREFUSED) : -1; 335219820Sjeff 336219820Sjeff VALGRIND_MAKE_MEM_DEFINED(resp, sizeof *resp); 337219820Sjeff 338219820Sjeff param->service_id = resp->service_id; 339219820Sjeff param->service_mask = resp->service_mask; 340219820Sjeff param->local_id = resp->local_id; 341219820Sjeff param->remote_id = resp->remote_id; 342219820Sjeff return 0; 343219820Sjeff} 344219820Sjeff 345219820Sjeffint ib_cm_init_qp_attr(struct ib_cm_id *cm_id, 346219820Sjeff struct ibv_qp_attr *qp_attr, 347219820Sjeff int *qp_attr_mask) 348219820Sjeff{ 349219820Sjeff struct ibv_kern_qp_attr *resp; 350219820Sjeff struct cm_abi_init_qp_attr *cmd; 351219820Sjeff void *msg; 352219820Sjeff int result; 353219820Sjeff int size; 354219820Sjeff 355219820Sjeff if (!qp_attr || !qp_attr_mask) 356219820Sjeff return ERR(EINVAL); 357219820Sjeff 358219820Sjeff CM_CREATE_MSG_CMD_RESP(msg, cmd, resp, IB_USER_CM_CMD_INIT_QP_ATTR, size); 359219820Sjeff cmd->id = cm_id->handle; 360219820Sjeff cmd->qp_state = qp_attr->qp_state; 361219820Sjeff 362219820Sjeff result = write(cm_id->device->fd, msg, size); 363219820Sjeff if (result != size) 364219820Sjeff return (result >= 0) ? ERR(ECONNREFUSED) : result; 365219820Sjeff 366219820Sjeff VALGRIND_MAKE_MEM_DEFINED(resp, sizeof *resp); 367219820Sjeff 368219820Sjeff *qp_attr_mask = resp->qp_attr_mask; 369219820Sjeff ibv_copy_qp_attr_from_kern(qp_attr, resp); 370219820Sjeff 371219820Sjeff return 0; 372219820Sjeff} 373219820Sjeff 374219820Sjeffint ib_cm_listen(struct ib_cm_id *cm_id, 375219820Sjeff uint64_t service_id, 376219820Sjeff uint64_t service_mask) 377219820Sjeff{ 378219820Sjeff struct cm_abi_listen *cmd; 379219820Sjeff void *msg; 380219820Sjeff int result; 381219820Sjeff int size; 382219820Sjeff 383219820Sjeff CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_LISTEN, size); 384219820Sjeff cmd->id = cm_id->handle; 385219820Sjeff cmd->service_id = service_id; 386219820Sjeff cmd->service_mask = service_mask; 387219820Sjeff 388219820Sjeff result = write(cm_id->device->fd, msg, size); 389219820Sjeff if (result != size) 390219820Sjeff return (result >= 0) ? ERR(ECONNREFUSED) : -1; 391219820Sjeff 392219820Sjeff return 0; 393219820Sjeff} 394219820Sjeff 395219820Sjeffint ib_cm_send_req(struct ib_cm_id *cm_id, struct ib_cm_req_param *param) 396219820Sjeff{ 397219820Sjeff struct ibv_kern_path_rec *p_path; 398219820Sjeff struct ibv_kern_path_rec *a_path; 399219820Sjeff struct cm_abi_req *cmd; 400219820Sjeff void *msg; 401219820Sjeff int result; 402219820Sjeff int size; 403219820Sjeff 404219820Sjeff if (!param) 405219820Sjeff return ERR(EINVAL); 406219820Sjeff 407219820Sjeff CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_SEND_REQ, size); 408219820Sjeff cmd->id = cm_id->handle; 409219820Sjeff cmd->qpn = param->qp_num; 410219820Sjeff cmd->qp_type = param->qp_type; 411219820Sjeff cmd->psn = param->starting_psn; 412219820Sjeff cmd->sid = param->service_id; 413219820Sjeff cmd->peer_to_peer = param->peer_to_peer; 414219820Sjeff cmd->responder_resources = param->responder_resources; 415219820Sjeff cmd->initiator_depth = param->initiator_depth; 416219820Sjeff cmd->remote_cm_response_timeout = param->remote_cm_response_timeout; 417219820Sjeff cmd->flow_control = param->flow_control; 418219820Sjeff cmd->local_cm_response_timeout = param->local_cm_response_timeout; 419219820Sjeff cmd->retry_count = param->retry_count; 420219820Sjeff cmd->rnr_retry_count = param->rnr_retry_count; 421219820Sjeff cmd->max_cm_retries = param->max_cm_retries; 422219820Sjeff cmd->srq = param->srq; 423219820Sjeff 424219820Sjeff if (param->primary_path) { 425219820Sjeff p_path = alloca(sizeof(*p_path)); 426219820Sjeff if (!p_path) 427219820Sjeff return ERR(ENOMEM); 428219820Sjeff 429219820Sjeff ibv_copy_path_rec_to_kern(p_path, param->primary_path); 430219820Sjeff cmd->primary_path = (uintptr_t) p_path; 431219820Sjeff } 432219820Sjeff 433219820Sjeff if (param->alternate_path) { 434219820Sjeff a_path = alloca(sizeof(*a_path)); 435219820Sjeff if (!a_path) 436219820Sjeff return ERR(ENOMEM); 437219820Sjeff 438219820Sjeff ibv_copy_path_rec_to_kern(a_path, param->alternate_path); 439219820Sjeff cmd->alternate_path = (uintptr_t) a_path; 440219820Sjeff } 441219820Sjeff 442219820Sjeff if (param->private_data && param->private_data_len) { 443219820Sjeff cmd->data = (uintptr_t) param->private_data; 444219820Sjeff cmd->len = param->private_data_len; 445219820Sjeff } 446219820Sjeff 447219820Sjeff result = write(cm_id->device->fd, msg, size); 448219820Sjeff if (result != size) 449219820Sjeff return (result >= 0) ? ERR(ECONNREFUSED) : -1; 450219820Sjeff 451219820Sjeff return 0; 452219820Sjeff} 453219820Sjeff 454219820Sjeffint ib_cm_send_rep(struct ib_cm_id *cm_id, struct ib_cm_rep_param *param) 455219820Sjeff{ 456219820Sjeff struct cm_abi_rep *cmd; 457219820Sjeff void *msg; 458219820Sjeff int result; 459219820Sjeff int size; 460219820Sjeff 461219820Sjeff if (!param) 462219820Sjeff return ERR(EINVAL); 463219820Sjeff 464219820Sjeff CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_SEND_REP, size); 465219820Sjeff cmd->uid = (uintptr_t) container_of(cm_id, struct cm_id_private, id); 466219820Sjeff cmd->id = cm_id->handle; 467219820Sjeff cmd->qpn = param->qp_num; 468219820Sjeff cmd->psn = param->starting_psn; 469219820Sjeff cmd->responder_resources = param->responder_resources; 470219820Sjeff cmd->initiator_depth = param->initiator_depth; 471219820Sjeff cmd->target_ack_delay = param->target_ack_delay; 472219820Sjeff cmd->failover_accepted = param->failover_accepted; 473219820Sjeff cmd->flow_control = param->flow_control; 474219820Sjeff cmd->rnr_retry_count = param->rnr_retry_count; 475219820Sjeff cmd->srq = param->srq; 476219820Sjeff 477219820Sjeff if (param->private_data && param->private_data_len) { 478219820Sjeff cmd->data = (uintptr_t) param->private_data; 479219820Sjeff cmd->len = param->private_data_len; 480219820Sjeff } 481219820Sjeff 482219820Sjeff result = write(cm_id->device->fd, msg, size); 483219820Sjeff if (result != size) 484219820Sjeff return (result >= 0) ? ERR(ECONNREFUSED) : -1; 485219820Sjeff 486219820Sjeff return 0; 487219820Sjeff} 488219820Sjeff 489219820Sjeffstatic inline int cm_send_private_data(struct ib_cm_id *cm_id, 490219820Sjeff uint32_t type, 491219820Sjeff void *private_data, 492219820Sjeff uint8_t private_data_len) 493219820Sjeff{ 494219820Sjeff struct cm_abi_private_data *cmd; 495219820Sjeff void *msg; 496219820Sjeff int result; 497219820Sjeff int size; 498219820Sjeff 499219820Sjeff CM_CREATE_MSG_CMD(msg, cmd, type, size); 500219820Sjeff cmd->id = cm_id->handle; 501219820Sjeff 502219820Sjeff if (private_data && private_data_len) { 503219820Sjeff cmd->data = (uintptr_t) private_data; 504219820Sjeff cmd->len = private_data_len; 505219820Sjeff } 506219820Sjeff 507219820Sjeff result = write(cm_id->device->fd, msg, size); 508219820Sjeff if (result != size) 509219820Sjeff return (result >= 0) ? ERR(ECONNREFUSED) : -1; 510219820Sjeff 511219820Sjeff return 0; 512219820Sjeff} 513219820Sjeff 514219820Sjeffint ib_cm_send_rtu(struct ib_cm_id *cm_id, 515219820Sjeff void *private_data, 516219820Sjeff uint8_t private_data_len) 517219820Sjeff{ 518219820Sjeff return cm_send_private_data(cm_id, IB_USER_CM_CMD_SEND_RTU, 519219820Sjeff private_data, private_data_len); 520219820Sjeff} 521219820Sjeff 522219820Sjeffint ib_cm_send_dreq(struct ib_cm_id *cm_id, 523219820Sjeff void *private_data, 524219820Sjeff uint8_t private_data_len) 525219820Sjeff{ 526219820Sjeff return cm_send_private_data(cm_id, IB_USER_CM_CMD_SEND_DREQ, 527219820Sjeff private_data, private_data_len); 528219820Sjeff} 529219820Sjeff 530219820Sjeffint ib_cm_send_drep(struct ib_cm_id *cm_id, 531219820Sjeff void *private_data, 532219820Sjeff uint8_t private_data_len) 533219820Sjeff{ 534219820Sjeff return cm_send_private_data(cm_id, IB_USER_CM_CMD_SEND_DREP, 535219820Sjeff private_data, private_data_len); 536219820Sjeff} 537219820Sjeff 538219820Sjeffstatic int cm_establish(struct ib_cm_id *cm_id) 539219820Sjeff{ 540219820Sjeff struct cm_abi_establish *cmd; 541219820Sjeff void *msg; 542219820Sjeff int result; 543219820Sjeff int size; 544219820Sjeff 545219820Sjeff CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_ESTABLISH, size); 546219820Sjeff cmd->id = cm_id->handle; 547219820Sjeff 548219820Sjeff result = write(cm_id->device->fd, msg, size); 549219820Sjeff if (result != size) 550219820Sjeff return (result >= 0) ? ERR(ECONNREFUSED) : -1; 551219820Sjeff 552219820Sjeff return 0; 553219820Sjeff} 554219820Sjeff 555219820Sjeffint ib_cm_notify(struct ib_cm_id *cm_id, enum ibv_event_type event) 556219820Sjeff{ 557219820Sjeff struct cm_abi_notify *cmd; 558219820Sjeff void *msg; 559219820Sjeff int result; 560219820Sjeff int size; 561219820Sjeff 562219820Sjeff if (abi_ver == 4) { 563219820Sjeff if (event == IBV_EVENT_COMM_EST) 564219820Sjeff return cm_establish(cm_id); 565219820Sjeff else 566219820Sjeff return ERR(EINVAL); 567219820Sjeff } 568219820Sjeff 569219820Sjeff CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_NOTIFY, size); 570219820Sjeff cmd->id = cm_id->handle; 571219820Sjeff cmd->event = event; 572219820Sjeff 573219820Sjeff result = write(cm_id->device->fd, msg, size); 574219820Sjeff if (result != size) 575219820Sjeff return (result >= 0) ? ERR(ECONNREFUSED) : -1; 576219820Sjeff 577219820Sjeff return 0; 578219820Sjeff} 579219820Sjeff 580219820Sjeffstatic inline int cm_send_status(struct ib_cm_id *cm_id, 581219820Sjeff uint32_t type, 582219820Sjeff int status, 583219820Sjeff void *info, 584219820Sjeff uint8_t info_length, 585219820Sjeff void *private_data, 586219820Sjeff uint8_t private_data_len) 587219820Sjeff{ 588219820Sjeff struct cm_abi_info *cmd; 589219820Sjeff void *msg; 590219820Sjeff int result; 591219820Sjeff int size; 592219820Sjeff 593219820Sjeff CM_CREATE_MSG_CMD(msg, cmd, type, size); 594219820Sjeff cmd->id = cm_id->handle; 595219820Sjeff cmd->status = status; 596219820Sjeff 597219820Sjeff if (private_data && private_data_len) { 598219820Sjeff cmd->data = (uintptr_t) private_data; 599219820Sjeff cmd->data_len = private_data_len; 600219820Sjeff } 601219820Sjeff 602219820Sjeff if (info && info_length) { 603219820Sjeff cmd->info = (uintptr_t) info; 604219820Sjeff cmd->info_len = info_length; 605219820Sjeff } 606219820Sjeff 607219820Sjeff result = write(cm_id->device->fd, msg, size); 608219820Sjeff if (result != size) 609219820Sjeff return (result >= 0) ? ERR(ECONNREFUSED) : -1; 610219820Sjeff 611219820Sjeff return 0; 612219820Sjeff} 613219820Sjeff 614219820Sjeffint ib_cm_send_rej(struct ib_cm_id *cm_id, 615219820Sjeff enum ib_cm_rej_reason reason, 616219820Sjeff void *ari, 617219820Sjeff uint8_t ari_length, 618219820Sjeff void *private_data, 619219820Sjeff uint8_t private_data_len) 620219820Sjeff{ 621219820Sjeff return cm_send_status(cm_id, IB_USER_CM_CMD_SEND_REJ, reason, 622219820Sjeff ari, ari_length, 623219820Sjeff private_data, private_data_len); 624219820Sjeff} 625219820Sjeff 626219820Sjeffint ib_cm_send_apr(struct ib_cm_id *cm_id, 627219820Sjeff enum ib_cm_apr_status status, 628219820Sjeff void *info, 629219820Sjeff uint8_t info_length, 630219820Sjeff void *private_data, 631219820Sjeff uint8_t private_data_len) 632219820Sjeff{ 633219820Sjeff return cm_send_status(cm_id, IB_USER_CM_CMD_SEND_APR, status, 634219820Sjeff info, info_length, 635219820Sjeff private_data, private_data_len); 636219820Sjeff} 637219820Sjeff 638219820Sjeffint ib_cm_send_mra(struct ib_cm_id *cm_id, 639219820Sjeff uint8_t service_timeout, 640219820Sjeff void *private_data, 641219820Sjeff uint8_t private_data_len) 642219820Sjeff{ 643219820Sjeff struct cm_abi_mra *cmd; 644219820Sjeff void *msg; 645219820Sjeff int result; 646219820Sjeff int size; 647219820Sjeff 648219820Sjeff CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_SEND_MRA, size); 649219820Sjeff cmd->id = cm_id->handle; 650219820Sjeff cmd->timeout = service_timeout; 651219820Sjeff 652219820Sjeff if (private_data && private_data_len) { 653219820Sjeff cmd->data = (uintptr_t) private_data; 654219820Sjeff cmd->len = private_data_len; 655219820Sjeff } 656219820Sjeff 657219820Sjeff result = write(cm_id->device->fd, msg, size); 658219820Sjeff if (result != size) 659219820Sjeff return (result >= 0) ? ERR(ECONNREFUSED) : result; 660219820Sjeff 661219820Sjeff return 0; 662219820Sjeff} 663219820Sjeff 664219820Sjeffint ib_cm_send_lap(struct ib_cm_id *cm_id, 665219820Sjeff struct ibv_sa_path_rec *alternate_path, 666219820Sjeff void *private_data, 667219820Sjeff uint8_t private_data_len) 668219820Sjeff{ 669219820Sjeff struct ibv_kern_path_rec *abi_path; 670219820Sjeff struct cm_abi_lap *cmd; 671219820Sjeff void *msg; 672219820Sjeff int result; 673219820Sjeff int size; 674219820Sjeff 675219820Sjeff CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_SEND_LAP, size); 676219820Sjeff cmd->id = cm_id->handle; 677219820Sjeff 678219820Sjeff if (alternate_path) { 679219820Sjeff abi_path = alloca(sizeof(*abi_path)); 680219820Sjeff if (!abi_path) 681219820Sjeff return ERR(ENOMEM); 682219820Sjeff 683219820Sjeff ibv_copy_path_rec_to_kern(abi_path, alternate_path); 684219820Sjeff cmd->path = (uintptr_t) abi_path; 685219820Sjeff } 686219820Sjeff 687219820Sjeff if (private_data && private_data_len) { 688219820Sjeff cmd->data = (uintptr_t) private_data; 689219820Sjeff cmd->len = private_data_len; 690219820Sjeff } 691219820Sjeff 692219820Sjeff result = write(cm_id->device->fd, msg, size); 693219820Sjeff if (result != size) 694219820Sjeff return (result >= 0) ? ERR(ECONNREFUSED) : -1; 695219820Sjeff 696219820Sjeff return 0; 697219820Sjeff} 698219820Sjeff 699219820Sjeffint ib_cm_send_sidr_req(struct ib_cm_id *cm_id, 700219820Sjeff struct ib_cm_sidr_req_param *param) 701219820Sjeff{ 702219820Sjeff struct ibv_kern_path_rec *abi_path; 703219820Sjeff struct cm_abi_sidr_req *cmd; 704219820Sjeff void *msg; 705219820Sjeff int result; 706219820Sjeff int size; 707219820Sjeff 708219820Sjeff if (!param) 709219820Sjeff return ERR(EINVAL); 710219820Sjeff 711219820Sjeff CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_SEND_SIDR_REQ, size); 712219820Sjeff cmd->id = cm_id->handle; 713219820Sjeff cmd->sid = param->service_id; 714219820Sjeff cmd->timeout = param->timeout_ms; 715219820Sjeff cmd->pkey = param->path->pkey; 716219820Sjeff cmd->max_cm_retries = param->max_cm_retries; 717219820Sjeff 718219820Sjeff if (param->path) { 719219820Sjeff abi_path = alloca(sizeof(*abi_path)); 720219820Sjeff if (!abi_path) 721219820Sjeff return ERR(ENOMEM); 722219820Sjeff 723219820Sjeff ibv_copy_path_rec_to_kern(abi_path, param->path); 724219820Sjeff cmd->path = (uintptr_t) abi_path; 725219820Sjeff } 726219820Sjeff 727219820Sjeff if (param->private_data && param->private_data_len) { 728219820Sjeff cmd->data = (uintptr_t) param->private_data; 729219820Sjeff cmd->len = param->private_data_len; 730219820Sjeff } 731219820Sjeff 732219820Sjeff result = write(cm_id->device->fd, msg, size); 733219820Sjeff if (result != size) 734219820Sjeff return (result >= 0) ? ERR(ECONNREFUSED) : result; 735219820Sjeff 736219820Sjeff return 0; 737219820Sjeff} 738219820Sjeff 739219820Sjeffint ib_cm_send_sidr_rep(struct ib_cm_id *cm_id, 740219820Sjeff struct ib_cm_sidr_rep_param *param) 741219820Sjeff{ 742219820Sjeff struct cm_abi_sidr_rep *cmd; 743219820Sjeff void *msg; 744219820Sjeff int result; 745219820Sjeff int size; 746219820Sjeff 747219820Sjeff if (!param) 748219820Sjeff return ERR(EINVAL); 749219820Sjeff 750219820Sjeff CM_CREATE_MSG_CMD(msg, cmd, IB_USER_CM_CMD_SEND_SIDR_REP, size); 751219820Sjeff cmd->id = cm_id->handle; 752219820Sjeff cmd->qpn = param->qp_num; 753219820Sjeff cmd->qkey = param->qkey; 754219820Sjeff cmd->status = param->status; 755219820Sjeff 756219820Sjeff if (param->private_data && param->private_data_len) { 757219820Sjeff cmd->data = (uintptr_t) param->private_data; 758219820Sjeff cmd->data_len = param->private_data_len; 759219820Sjeff } 760219820Sjeff 761219820Sjeff if (param->info && param->info_length) { 762219820Sjeff cmd->info = (uintptr_t) param->info; 763219820Sjeff cmd->info_len = param->info_length; 764219820Sjeff } 765219820Sjeff 766219820Sjeff result = write(cm_id->device->fd, msg, size); 767219820Sjeff if (result != size) 768219820Sjeff return (result >= 0) ? ERR(ECONNREFUSED) : -1; 769219820Sjeff 770219820Sjeff return 0; 771219820Sjeff} 772219820Sjeff 773219820Sjeffstatic void cm_event_req_get(struct ib_cm_req_event_param *ureq, 774219820Sjeff struct cm_abi_req_event_resp *kreq) 775219820Sjeff{ 776219820Sjeff ureq->remote_ca_guid = kreq->remote_ca_guid; 777219820Sjeff ureq->remote_qkey = kreq->remote_qkey; 778219820Sjeff ureq->remote_qpn = kreq->remote_qpn; 779219820Sjeff ureq->qp_type = kreq->qp_type; 780219820Sjeff ureq->starting_psn = kreq->starting_psn; 781219820Sjeff ureq->responder_resources = kreq->responder_resources; 782219820Sjeff ureq->initiator_depth = kreq->initiator_depth; 783219820Sjeff ureq->local_cm_response_timeout = kreq->local_cm_response_timeout; 784219820Sjeff ureq->flow_control = kreq->flow_control; 785219820Sjeff ureq->remote_cm_response_timeout = kreq->remote_cm_response_timeout; 786219820Sjeff ureq->retry_count = kreq->retry_count; 787219820Sjeff ureq->rnr_retry_count = kreq->rnr_retry_count; 788219820Sjeff ureq->srq = kreq->srq; 789219820Sjeff ureq->port = kreq->port; 790219820Sjeff 791219820Sjeff ibv_copy_path_rec_from_kern(ureq->primary_path, &kreq->primary_path); 792219820Sjeff if (ureq->alternate_path) 793219820Sjeff ibv_copy_path_rec_from_kern(ureq->alternate_path, 794219820Sjeff &kreq->alternate_path); 795219820Sjeff} 796219820Sjeff 797219820Sjeffstatic void cm_event_rep_get(struct ib_cm_rep_event_param *urep, 798219820Sjeff struct cm_abi_rep_event_resp *krep) 799219820Sjeff{ 800219820Sjeff urep->remote_ca_guid = krep->remote_ca_guid; 801219820Sjeff urep->remote_qkey = krep->remote_qkey; 802219820Sjeff urep->remote_qpn = krep->remote_qpn; 803219820Sjeff urep->starting_psn = krep->starting_psn; 804219820Sjeff urep->responder_resources = krep->responder_resources; 805219820Sjeff urep->initiator_depth = krep->initiator_depth; 806219820Sjeff urep->target_ack_delay = krep->target_ack_delay; 807219820Sjeff urep->failover_accepted = krep->failover_accepted; 808219820Sjeff urep->flow_control = krep->flow_control; 809219820Sjeff urep->rnr_retry_count = krep->rnr_retry_count; 810219820Sjeff urep->srq = krep->srq; 811219820Sjeff} 812219820Sjeff 813219820Sjeffstatic void cm_event_sidr_rep_get(struct ib_cm_sidr_rep_event_param *urep, 814219820Sjeff struct cm_abi_sidr_rep_event_resp *krep) 815219820Sjeff{ 816219820Sjeff urep->status = krep->status; 817219820Sjeff urep->qkey = krep->qkey; 818219820Sjeff urep->qpn = krep->qpn; 819219820Sjeff}; 820219820Sjeff 821219820Sjeffint ib_cm_get_event(struct ib_cm_device *device, struct ib_cm_event **event) 822219820Sjeff{ 823219820Sjeff struct cm_id_private *cm_id_priv; 824219820Sjeff struct cm_abi_cmd_hdr *hdr; 825219820Sjeff struct cm_abi_event_get *cmd; 826219820Sjeff struct cm_abi_event_resp *resp; 827219820Sjeff struct ib_cm_event *evt = NULL; 828219820Sjeff struct ibv_sa_path_rec *path_a = NULL; 829219820Sjeff struct ibv_sa_path_rec *path_b = NULL; 830219820Sjeff void *data = NULL; 831219820Sjeff void *info = NULL; 832219820Sjeff void *msg; 833219820Sjeff int result = 0; 834219820Sjeff int size; 835219820Sjeff 836219820Sjeff if (!event) 837219820Sjeff return ERR(EINVAL); 838219820Sjeff 839219820Sjeff size = sizeof(*hdr) + sizeof(*cmd); 840219820Sjeff msg = alloca(size); 841219820Sjeff if (!msg) 842219820Sjeff return ERR(ENOMEM); 843219820Sjeff 844219820Sjeff hdr = msg; 845219820Sjeff cmd = msg + sizeof(*hdr); 846219820Sjeff 847219820Sjeff hdr->cmd = IB_USER_CM_CMD_EVENT; 848219820Sjeff hdr->in = sizeof(*cmd); 849219820Sjeff hdr->out = sizeof(*resp); 850219820Sjeff 851219820Sjeff memset(cmd, 0, sizeof(*cmd)); 852219820Sjeff 853219820Sjeff resp = alloca(sizeof(*resp)); 854219820Sjeff if (!resp) 855219820Sjeff return ERR(ENOMEM); 856219820Sjeff 857219820Sjeff cmd->response = (uintptr_t) resp; 858219820Sjeff cmd->data_len = (uint8_t)(~0U); 859219820Sjeff cmd->info_len = (uint8_t)(~0U); 860219820Sjeff 861219820Sjeff data = malloc(cmd->data_len); 862219820Sjeff if (!data) { 863219820Sjeff result = ERR(ENOMEM); 864219820Sjeff goto done; 865219820Sjeff } 866219820Sjeff 867219820Sjeff info = malloc(cmd->info_len); 868219820Sjeff if (!info) { 869219820Sjeff result = ERR(ENOMEM); 870219820Sjeff goto done; 871219820Sjeff } 872219820Sjeff 873219820Sjeff cmd->data = (uintptr_t) data; 874219820Sjeff cmd->info = (uintptr_t) info; 875219820Sjeff 876219820Sjeff result = write(device->fd, msg, size); 877219820Sjeff if (result != size) { 878219820Sjeff result = (result >= 0) ? ERR(ECONNREFUSED) : -1; 879219820Sjeff goto done; 880219820Sjeff } 881219820Sjeff 882219820Sjeff VALGRIND_MAKE_MEM_DEFINED(resp, sizeof *resp); 883219820Sjeff 884219820Sjeff /* 885219820Sjeff * decode event. 886219820Sjeff */ 887219820Sjeff evt = malloc(sizeof(*evt)); 888219820Sjeff if (!evt) { 889219820Sjeff result = ERR(ENOMEM); 890219820Sjeff goto done; 891219820Sjeff } 892219820Sjeff memset(evt, 0, sizeof(*evt)); 893219820Sjeff evt->cm_id = (void *) (uintptr_t) resp->uid; 894219820Sjeff evt->event = resp->event; 895219820Sjeff 896219820Sjeff if (resp->present & CM_ABI_PRES_PRIMARY) { 897219820Sjeff path_a = malloc(sizeof(*path_a)); 898219820Sjeff if (!path_a) { 899219820Sjeff result = ERR(ENOMEM); 900219820Sjeff goto done; 901219820Sjeff } 902219820Sjeff } 903219820Sjeff 904219820Sjeff if (resp->present & CM_ABI_PRES_ALTERNATE) { 905219820Sjeff path_b = malloc(sizeof(*path_b)); 906219820Sjeff if (!path_b) { 907219820Sjeff result = ERR(ENOMEM); 908219820Sjeff goto done; 909219820Sjeff } 910219820Sjeff } 911219820Sjeff 912219820Sjeff switch (evt->event) { 913219820Sjeff case IB_CM_REQ_RECEIVED: 914219820Sjeff evt->param.req_rcvd.listen_id = evt->cm_id; 915219820Sjeff cm_id_priv = ib_cm_alloc_id(evt->cm_id->device, 916219820Sjeff evt->cm_id->context); 917219820Sjeff if (!cm_id_priv) { 918219820Sjeff result = ERR(ENOMEM); 919219820Sjeff goto done; 920219820Sjeff } 921219820Sjeff cm_id_priv->id.handle = resp->id; 922219820Sjeff evt->cm_id = &cm_id_priv->id; 923219820Sjeff evt->param.req_rcvd.primary_path = path_a; 924219820Sjeff evt->param.req_rcvd.alternate_path = path_b; 925219820Sjeff path_a = NULL; 926219820Sjeff path_b = NULL; 927219820Sjeff cm_event_req_get(&evt->param.req_rcvd, &resp->u.req_resp); 928219820Sjeff break; 929219820Sjeff case IB_CM_REP_RECEIVED: 930219820Sjeff cm_event_rep_get(&evt->param.rep_rcvd, &resp->u.rep_resp); 931219820Sjeff break; 932219820Sjeff case IB_CM_MRA_RECEIVED: 933219820Sjeff evt->param.mra_rcvd.service_timeout = resp->u.mra_resp.timeout; 934219820Sjeff break; 935219820Sjeff case IB_CM_REJ_RECEIVED: 936219820Sjeff evt->param.rej_rcvd.reason = resp->u.rej_resp.reason; 937219820Sjeff evt->param.rej_rcvd.ari = info; 938219820Sjeff info = NULL; 939219820Sjeff break; 940219820Sjeff case IB_CM_LAP_RECEIVED: 941219820Sjeff evt->param.lap_rcvd.alternate_path = path_b; 942219820Sjeff path_b = NULL; 943219820Sjeff ibv_copy_path_rec_from_kern(evt->param.lap_rcvd.alternate_path, 944219820Sjeff &resp->u.lap_resp.path); 945219820Sjeff break; 946219820Sjeff case IB_CM_APR_RECEIVED: 947219820Sjeff evt->param.apr_rcvd.ap_status = resp->u.apr_resp.status; 948219820Sjeff evt->param.apr_rcvd.apr_info = info; 949219820Sjeff info = NULL; 950219820Sjeff break; 951219820Sjeff case IB_CM_SIDR_REQ_RECEIVED: 952219820Sjeff evt->param.sidr_req_rcvd.listen_id = evt->cm_id; 953219820Sjeff cm_id_priv = ib_cm_alloc_id(evt->cm_id->device, 954219820Sjeff evt->cm_id->context); 955219820Sjeff if (!cm_id_priv) { 956219820Sjeff result = ERR(ENOMEM); 957219820Sjeff goto done; 958219820Sjeff } 959219820Sjeff cm_id_priv->id.handle = resp->id; 960219820Sjeff evt->cm_id = &cm_id_priv->id; 961219820Sjeff evt->param.sidr_req_rcvd.pkey = resp->u.sidr_req_resp.pkey; 962219820Sjeff evt->param.sidr_req_rcvd.port = resp->u.sidr_req_resp.port; 963219820Sjeff break; 964219820Sjeff case IB_CM_SIDR_REP_RECEIVED: 965219820Sjeff cm_event_sidr_rep_get(&evt->param.sidr_rep_rcvd, 966219820Sjeff &resp->u.sidr_rep_resp); 967219820Sjeff evt->param.sidr_rep_rcvd.info = info; 968219820Sjeff info = NULL; 969219820Sjeff break; 970219820Sjeff default: 971219820Sjeff evt->param.send_status = resp->u.send_status; 972219820Sjeff break; 973219820Sjeff } 974219820Sjeff 975219820Sjeff if (resp->present & CM_ABI_PRES_DATA) { 976219820Sjeff evt->private_data = data; 977219820Sjeff data = NULL; 978219820Sjeff } 979219820Sjeff 980219820Sjeff *event = evt; 981219820Sjeff evt = NULL; 982219820Sjeff result = 0; 983219820Sjeffdone: 984219820Sjeff if (data) 985219820Sjeff free(data); 986219820Sjeff if (info) 987219820Sjeff free(info); 988219820Sjeff if (path_a) 989219820Sjeff free(path_a); 990219820Sjeff if (path_b) 991219820Sjeff free(path_b); 992219820Sjeff if (evt) 993219820Sjeff free(evt); 994219820Sjeff 995219820Sjeff return result; 996219820Sjeff} 997219820Sjeff 998219820Sjeffint ib_cm_ack_event(struct ib_cm_event *event) 999219820Sjeff{ 1000219820Sjeff struct cm_id_private *cm_id_priv; 1001219820Sjeff 1002219820Sjeff if (!event) 1003219820Sjeff return ERR(EINVAL); 1004219820Sjeff 1005219820Sjeff if (event->private_data) 1006219820Sjeff free(event->private_data); 1007219820Sjeff 1008219820Sjeff cm_id_priv = container_of(event->cm_id, struct cm_id_private, id); 1009219820Sjeff 1010219820Sjeff switch (event->event) { 1011219820Sjeff case IB_CM_REQ_RECEIVED: 1012219820Sjeff cm_id_priv = container_of(event->param.req_rcvd.listen_id, 1013219820Sjeff struct cm_id_private, id); 1014219820Sjeff free(event->param.req_rcvd.primary_path); 1015219820Sjeff if (event->param.req_rcvd.alternate_path) 1016219820Sjeff free(event->param.req_rcvd.alternate_path); 1017219820Sjeff break; 1018219820Sjeff case IB_CM_REJ_RECEIVED: 1019219820Sjeff if (event->param.rej_rcvd.ari) 1020219820Sjeff free(event->param.rej_rcvd.ari); 1021219820Sjeff break; 1022219820Sjeff case IB_CM_LAP_RECEIVED: 1023219820Sjeff free(event->param.lap_rcvd.alternate_path); 1024219820Sjeff break; 1025219820Sjeff case IB_CM_APR_RECEIVED: 1026219820Sjeff if (event->param.apr_rcvd.apr_info) 1027219820Sjeff free(event->param.apr_rcvd.apr_info); 1028219820Sjeff break; 1029219820Sjeff case IB_CM_SIDR_REQ_RECEIVED: 1030219820Sjeff cm_id_priv = container_of(event->param.sidr_req_rcvd.listen_id, 1031219820Sjeff struct cm_id_private, id); 1032219820Sjeff break; 1033219820Sjeff case IB_CM_SIDR_REP_RECEIVED: 1034219820Sjeff if (event->param.sidr_rep_rcvd.info) 1035219820Sjeff free(event->param.sidr_rep_rcvd.info); 1036219820Sjeff default: 1037219820Sjeff break; 1038219820Sjeff } 1039219820Sjeff 1040219820Sjeff pthread_mutex_lock(&cm_id_priv->mut); 1041219820Sjeff cm_id_priv->events_completed++; 1042219820Sjeff pthread_cond_signal(&cm_id_priv->cond); 1043219820Sjeff pthread_mutex_unlock(&cm_id_priv->mut); 1044219820Sjeff 1045219820Sjeff free(event); 1046219820Sjeff return 0; 1047219820Sjeff} 1048