1219820Sjeff/* 2219820Sjeff * Copyright (c) 2005-2006 Intel Corporation. All rights reserved. 3219820Sjeff * 4219820Sjeff * This software is available to you under a choice of one of two 5219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 6219820Sjeff * General Public License (GPL) Version 2, available from the file 7219820Sjeff * COPYING in the main directory of this source tree, or the 8219820Sjeff * OpenIB.org BSD license below: 9219820Sjeff * 10219820Sjeff * Redistribution and use in source and binary forms, with or 11219820Sjeff * without modification, are permitted provided that the following 12219820Sjeff * conditions are met: 13219820Sjeff * 14219820Sjeff * - Redistributions of source code must retain the above 15219820Sjeff * copyright notice, this list of conditions and the following 16219820Sjeff * disclaimer. 17219820Sjeff * 18219820Sjeff * - Redistributions in binary form must reproduce the above 19219820Sjeff * copyright notice, this list of conditions and the following 20219820Sjeff * disclaimer in the documentation and/or other materials 21219820Sjeff * provided with the distribution. 22219820Sjeff * 23219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30219820Sjeff * SOFTWARE. 31219820Sjeff * 32219820Sjeff * $Id: cm.c 3453 2005-09-15 21:43:21Z sean.hefty $ 33219820Sjeff */ 34219820Sjeff 35219820Sjeff#if HAVE_CONFIG_H 36219820Sjeff# include <config.h> 37219820Sjeff#endif /* HAVE_CONFIG_H */ 38219820Sjeff 39219820Sjeff#include <stdlib.h> 40219820Sjeff#include <string.h> 41219820Sjeff#include <glob.h> 42219820Sjeff#include <stdio.h> 43219820Sjeff#include <fcntl.h> 44219820Sjeff#include <errno.h> 45219820Sjeff#include <stdint.h> 46219820Sjeff#include <poll.h> 47219820Sjeff#include <unistd.h> 48219820Sjeff#include <pthread.h> 49219820Sjeff#include <infiniband/endian.h> 50219820Sjeff#include <infiniband/byteswap.h> 51219820Sjeff#include <stddef.h> 52219820Sjeff 53219820Sjeff#include <infiniband/driver.h> 54219820Sjeff#include <infiniband/marshall.h> 55219820Sjeff#include <rdma/rdma_cma.h> 56219820Sjeff#include <rdma/rdma_cma_abi.h> 57219820Sjeff 58219820Sjeff#ifdef INCLUDE_VALGRIND 59219820Sjeff# include <valgrind/memcheck.h> 60219820Sjeff# ifndef VALGRIND_MAKE_MEM_DEFINED 61219820Sjeff# warning "Valgrind requested, but VALGRIND_MAKE_MEM_DEFINED undefined" 62219820Sjeff# endif 63219820Sjeff#endif 64219820Sjeff 65219820Sjeff#ifndef VALGRIND_MAKE_MEM_DEFINED 66219820Sjeff# define VALGRIND_MAKE_MEM_DEFINED(addr,len) 67219820Sjeff#endif 68219820Sjeff 69219820Sjeff#define PFX "librdmacm: " 70219820Sjeff 71219820Sjeff#if __BYTE_ORDER == __LITTLE_ENDIAN 72219820Sjeffstatic inline uint64_t htonll(uint64_t x) { return bswap_64(x); } 73219820Sjeffstatic inline uint64_t ntohll(uint64_t x) { return bswap_64(x); } 74219820Sjeff#else 75219820Sjeffstatic inline uint64_t htonll(uint64_t x) { return x; } 76219820Sjeffstatic inline uint64_t ntohll(uint64_t x) { return x; } 77219820Sjeff#endif 78219820Sjeff 79219820Sjeffstatic inline int ERR(int err) 80219820Sjeff{ 81219820Sjeff errno = err; 82219820Sjeff return -1; 83219820Sjeff} 84219820Sjeff 85219820Sjeff#define CMA_CREATE_MSG_CMD_RESP(msg, cmd, resp, type, size) \ 86219820Sjeffdo { \ 87219820Sjeff struct ucma_abi_cmd_hdr *hdr; \ 88219820Sjeff \ 89219820Sjeff size = sizeof(*hdr) + sizeof(*cmd); \ 90219820Sjeff msg = alloca(size); \ 91219820Sjeff if (!msg) \ 92219820Sjeff return ERR(ENOMEM); \ 93219820Sjeff hdr = msg; \ 94219820Sjeff cmd = msg + sizeof(*hdr); \ 95219820Sjeff hdr->cmd = type; \ 96219820Sjeff hdr->in = sizeof(*cmd); \ 97219820Sjeff hdr->out = sizeof(*resp); \ 98219820Sjeff memset(cmd, 0, sizeof(*cmd)); \ 99219820Sjeff resp = alloca(sizeof(*resp)); \ 100219820Sjeff if (!resp) \ 101219820Sjeff return ERR(ENOMEM); \ 102219820Sjeff cmd->response = (uintptr_t)resp;\ 103219820Sjeff} while (0) 104219820Sjeff 105219820Sjeff#define CMA_CREATE_MSG_CMD(msg, cmd, type, size) \ 106219820Sjeffdo { \ 107219820Sjeff struct ucma_abi_cmd_hdr *hdr; \ 108219820Sjeff \ 109219820Sjeff size = sizeof(*hdr) + sizeof(*cmd); \ 110219820Sjeff msg = alloca(size); \ 111219820Sjeff if (!msg) \ 112219820Sjeff return ERR(ENOMEM); \ 113219820Sjeff hdr = msg; \ 114219820Sjeff cmd = msg + sizeof(*hdr); \ 115219820Sjeff hdr->cmd = type; \ 116219820Sjeff hdr->in = sizeof(*cmd); \ 117219820Sjeff hdr->out = 0; \ 118219820Sjeff memset(cmd, 0, sizeof(*cmd)); \ 119219820Sjeff} while (0) 120219820Sjeff 121219820Sjeffstruct cma_device { 122219820Sjeff struct ibv_context *verbs; 123219820Sjeff uint64_t guid; 124219820Sjeff int port_cnt; 125219820Sjeff uint8_t max_initiator_depth; 126219820Sjeff uint8_t max_responder_resources; 127219820Sjeff}; 128219820Sjeff 129219820Sjeffstruct cma_id_private { 130219820Sjeff struct rdma_cm_id id; 131219820Sjeff struct cma_device *cma_dev; 132219820Sjeff int events_completed; 133219820Sjeff int connect_error; 134219820Sjeff pthread_cond_t cond; 135219820Sjeff pthread_mutex_t mut; 136219820Sjeff uint32_t handle; 137219820Sjeff struct cma_multicast *mc_list; 138219820Sjeff}; 139219820Sjeff 140219820Sjeffstruct cma_multicast { 141219820Sjeff struct cma_multicast *next; 142219820Sjeff struct cma_id_private *id_priv; 143219820Sjeff void *context; 144219820Sjeff int events_completed; 145219820Sjeff pthread_cond_t cond; 146219820Sjeff uint32_t handle; 147219820Sjeff union ibv_gid mgid; 148219820Sjeff uint16_t mlid; 149219820Sjeff struct sockaddr_storage addr; 150219820Sjeff}; 151219820Sjeff 152219820Sjeffstruct cma_event { 153219820Sjeff struct rdma_cm_event event; 154219820Sjeff uint8_t private_data[RDMA_MAX_PRIVATE_DATA]; 155219820Sjeff struct cma_id_private *id_priv; 156219820Sjeff struct cma_multicast *mc; 157219820Sjeff}; 158219820Sjeff 159219820Sjeffstatic struct cma_device *cma_dev_array; 160219820Sjeffstatic int cma_dev_cnt; 161219820Sjeffstatic pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; 162219820Sjeffstatic int abi_ver = RDMA_USER_CM_MAX_ABI_VERSION; 163219820Sjeff 164219820Sjeff#define container_of(ptr, type, field) \ 165219820Sjeff ((type *) ((void *)ptr - offsetof(type, field))) 166219820Sjeff 167219820Sjeffstatic void ucma_cleanup(void) 168219820Sjeff{ 169219820Sjeff if (cma_dev_cnt) { 170219820Sjeff while (cma_dev_cnt) 171219820Sjeff ibv_close_device(cma_dev_array[--cma_dev_cnt].verbs); 172219820Sjeff 173219820Sjeff free(cma_dev_array); 174219820Sjeff cma_dev_cnt = 0; 175219820Sjeff } 176219820Sjeff} 177219820Sjeff 178219820Sjeffstatic int check_abi_version(void) 179219820Sjeff{ 180219820Sjeff char value[8]; 181219820Sjeff 182219820Sjeff if ((ibv_read_sysfs_file(ibv_get_sysfs_path(), 183219820Sjeff "class/misc/rdma_cm/abi_version", 184219820Sjeff value, sizeof value) < 0) && 185219820Sjeff (ibv_read_sysfs_file(ibv_get_sysfs_path(), 186219820Sjeff "class/infiniband_ucma/abi_version", 187219820Sjeff value, sizeof value) < 0)) { 188219820Sjeff /* 189219820Sjeff * Older version of Linux do not have class/misc. To support 190219820Sjeff * backports, assume the most recent version of the ABI. If 191219820Sjeff * we're wrong, we'll simply fail later when calling the ABI. 192219820Sjeff */ 193219820Sjeff fprintf(stderr, "librdmacm: couldn't read ABI version.\n"); 194219820Sjeff fprintf(stderr, "librdmacm: assuming: %d\n", abi_ver); 195219820Sjeff return 0; 196219820Sjeff } 197219820Sjeff 198219820Sjeff abi_ver = strtol(value, NULL, 10); 199219820Sjeff if (abi_ver < RDMA_USER_CM_MIN_ABI_VERSION || 200219820Sjeff abi_ver > RDMA_USER_CM_MAX_ABI_VERSION) { 201219820Sjeff fprintf(stderr, "librdmacm: kernel ABI version %d " 202219820Sjeff "doesn't match library version %d.\n", 203219820Sjeff abi_ver, RDMA_USER_CM_MAX_ABI_VERSION); 204219820Sjeff return -1; 205219820Sjeff } 206219820Sjeff return 0; 207219820Sjeff} 208219820Sjeff 209219820Sjeffstatic int ucma_init(void) 210219820Sjeff{ 211219820Sjeff struct ibv_device **dev_list = NULL; 212219820Sjeff struct cma_device *cma_dev; 213219820Sjeff struct ibv_device_attr attr; 214219820Sjeff int i, ret, dev_cnt; 215219820Sjeff 216219820Sjeff pthread_mutex_lock(&mut); 217219820Sjeff if (cma_dev_cnt) { 218219820Sjeff pthread_mutex_unlock(&mut); 219219820Sjeff return 0; 220219820Sjeff } 221219820Sjeff 222219820Sjeff ret = check_abi_version(); 223219820Sjeff if (ret) 224219820Sjeff goto err1; 225219820Sjeff 226219820Sjeff dev_list = ibv_get_device_list(&dev_cnt); 227219820Sjeff if (!dev_list) { 228219820Sjeff printf("CMA: unable to get RDMA device list\n"); 229219820Sjeff ret = ERR(ENODEV); 230219820Sjeff goto err1; 231219820Sjeff } 232219820Sjeff 233219820Sjeff cma_dev_array = malloc(sizeof *cma_dev * dev_cnt); 234219820Sjeff if (!cma_dev_array) { 235219820Sjeff ret = ERR(ENOMEM); 236219820Sjeff goto err2; 237219820Sjeff } 238219820Sjeff 239219820Sjeff for (i = 0; dev_list[i];) { 240219820Sjeff cma_dev = &cma_dev_array[i]; 241219820Sjeff 242219820Sjeff cma_dev->guid = ibv_get_device_guid(dev_list[i]); 243219820Sjeff cma_dev->verbs = ibv_open_device(dev_list[i]); 244219820Sjeff if (!cma_dev->verbs) { 245219820Sjeff printf("CMA: unable to open RDMA device\n"); 246219820Sjeff ret = ERR(ENODEV); 247219820Sjeff goto err3; 248219820Sjeff } 249219820Sjeff 250219820Sjeff i++; 251219820Sjeff ret = ibv_query_device(cma_dev->verbs, &attr); 252219820Sjeff if (ret) { 253219820Sjeff printf("CMA: unable to query RDMA device\n"); 254219820Sjeff goto err3; 255219820Sjeff } 256219820Sjeff 257219820Sjeff cma_dev->port_cnt = attr.phys_port_cnt; 258219820Sjeff cma_dev->max_initiator_depth = (uint8_t) attr.max_qp_init_rd_atom; 259219820Sjeff cma_dev->max_responder_resources = (uint8_t) attr.max_qp_rd_atom; 260219820Sjeff } 261219820Sjeff 262219820Sjeff cma_dev_cnt = dev_cnt; 263219820Sjeff pthread_mutex_unlock(&mut); 264219820Sjeff ibv_free_device_list(dev_list); 265219820Sjeff return 0; 266219820Sjeff 267219820Sjefferr3: 268219820Sjeff while (i--) 269219820Sjeff ibv_close_device(cma_dev_array[i].verbs); 270219820Sjeff free(cma_dev_array); 271219820Sjefferr2: 272219820Sjeff ibv_free_device_list(dev_list); 273219820Sjefferr1: 274219820Sjeff pthread_mutex_unlock(&mut); 275219820Sjeff return ret; 276219820Sjeff} 277219820Sjeff 278219820Sjeffstruct ibv_context **rdma_get_devices(int *num_devices) 279219820Sjeff{ 280219820Sjeff struct ibv_context **devs = NULL; 281219820Sjeff int i; 282219820Sjeff 283219820Sjeff if (!cma_dev_cnt && ucma_init()) 284219820Sjeff goto out; 285219820Sjeff 286219820Sjeff devs = malloc(sizeof *devs * (cma_dev_cnt + 1)); 287219820Sjeff if (!devs) 288219820Sjeff goto out; 289219820Sjeff 290219820Sjeff for (i = 0; i < cma_dev_cnt; i++) 291219820Sjeff devs[i] = cma_dev_array[i].verbs; 292219820Sjeff devs[i] = NULL; 293219820Sjeffout: 294219820Sjeff if (num_devices) 295219820Sjeff *num_devices = devs ? cma_dev_cnt : 0; 296219820Sjeff return devs; 297219820Sjeff} 298219820Sjeff 299219820Sjeffvoid rdma_free_devices(struct ibv_context **list) 300219820Sjeff{ 301219820Sjeff free(list); 302219820Sjeff} 303219820Sjeff 304219820Sjeffstatic void __attribute__((destructor)) rdma_cma_fini(void) 305219820Sjeff{ 306219820Sjeff ucma_cleanup(); 307219820Sjeff} 308219820Sjeff 309219820Sjeffstruct rdma_event_channel *rdma_create_event_channel(void) 310219820Sjeff{ 311219820Sjeff struct rdma_event_channel *channel; 312219820Sjeff 313219820Sjeff if (!cma_dev_cnt && ucma_init()) 314219820Sjeff return NULL; 315219820Sjeff 316219820Sjeff channel = malloc(sizeof *channel); 317219820Sjeff if (!channel) 318219820Sjeff return NULL; 319219820Sjeff 320219820Sjeff channel->fd = open("/dev/rdma_cm", O_RDWR); 321219820Sjeff if (channel->fd < 0) { 322219820Sjeff printf("CMA: unable to open /dev/rdma_cm\n"); 323219820Sjeff goto err; 324219820Sjeff } 325219820Sjeff return channel; 326219820Sjefferr: 327219820Sjeff free(channel); 328219820Sjeff return NULL; 329219820Sjeff} 330219820Sjeff 331219820Sjeffvoid rdma_destroy_event_channel(struct rdma_event_channel *channel) 332219820Sjeff{ 333219820Sjeff close(channel->fd); 334219820Sjeff free(channel); 335219820Sjeff} 336219820Sjeff 337219820Sjeffstatic int ucma_get_device(struct cma_id_private *id_priv, uint64_t guid) 338219820Sjeff{ 339219820Sjeff struct cma_device *cma_dev; 340219820Sjeff int i; 341219820Sjeff 342219820Sjeff for (i = 0; i < cma_dev_cnt; i++) { 343219820Sjeff cma_dev = &cma_dev_array[i]; 344219820Sjeff if (cma_dev->guid == guid) { 345219820Sjeff id_priv->cma_dev = cma_dev; 346219820Sjeff id_priv->id.verbs = cma_dev->verbs; 347219820Sjeff return 0; 348219820Sjeff } 349219820Sjeff } 350219820Sjeff 351219820Sjeff return ERR(ENODEV); 352219820Sjeff} 353219820Sjeff 354219820Sjeffstatic void ucma_free_id(struct cma_id_private *id_priv) 355219820Sjeff{ 356219820Sjeff pthread_cond_destroy(&id_priv->cond); 357219820Sjeff pthread_mutex_destroy(&id_priv->mut); 358219820Sjeff if (id_priv->id.route.path_rec) 359219820Sjeff free(id_priv->id.route.path_rec); 360219820Sjeff free(id_priv); 361219820Sjeff} 362219820Sjeff 363219820Sjeffstatic struct cma_id_private *ucma_alloc_id(struct rdma_event_channel *channel, 364219820Sjeff void *context, 365219820Sjeff enum rdma_port_space ps) 366219820Sjeff{ 367219820Sjeff struct cma_id_private *id_priv; 368219820Sjeff 369219820Sjeff id_priv = malloc(sizeof *id_priv); 370219820Sjeff if (!id_priv) 371219820Sjeff return NULL; 372219820Sjeff 373219820Sjeff memset(id_priv, 0, sizeof *id_priv); 374219820Sjeff id_priv->id.context = context; 375219820Sjeff id_priv->id.ps = ps; 376219820Sjeff id_priv->id.channel = channel; 377219820Sjeff pthread_mutex_init(&id_priv->mut, NULL); 378219820Sjeff if (pthread_cond_init(&id_priv->cond, NULL)) 379219820Sjeff goto err; 380219820Sjeff 381219820Sjeff return id_priv; 382219820Sjeff 383219820Sjefferr: ucma_free_id(id_priv); 384219820Sjeff return NULL; 385219820Sjeff} 386219820Sjeff 387219820Sjeffint rdma_create_id(struct rdma_event_channel *channel, 388219820Sjeff struct rdma_cm_id **id, void *context, 389219820Sjeff enum rdma_port_space ps) 390219820Sjeff{ 391219820Sjeff struct ucma_abi_create_id_resp *resp; 392219820Sjeff struct ucma_abi_create_id *cmd; 393219820Sjeff struct cma_id_private *id_priv; 394219820Sjeff void *msg; 395219820Sjeff int ret, size; 396219820Sjeff 397219820Sjeff ret = cma_dev_cnt ? 0 : ucma_init(); 398219820Sjeff if (ret) 399219820Sjeff return ret; 400219820Sjeff 401219820Sjeff id_priv = ucma_alloc_id(channel, context, ps); 402219820Sjeff if (!id_priv) 403219820Sjeff return ERR(ENOMEM); 404219820Sjeff 405219820Sjeff CMA_CREATE_MSG_CMD_RESP(msg, cmd, resp, UCMA_CMD_CREATE_ID, size); 406219820Sjeff cmd->uid = (uintptr_t) id_priv; 407219820Sjeff cmd->ps = ps; 408219820Sjeff 409219820Sjeff ret = write(channel->fd, msg, size); 410219820Sjeff if (ret != size) 411219820Sjeff goto err; 412219820Sjeff 413219820Sjeff VALGRIND_MAKE_MEM_DEFINED(resp, sizeof *resp); 414219820Sjeff 415219820Sjeff id_priv->handle = resp->id; 416219820Sjeff *id = &id_priv->id; 417219820Sjeff return 0; 418219820Sjeff 419219820Sjefferr: ucma_free_id(id_priv); 420219820Sjeff return ret; 421219820Sjeff} 422219820Sjeff 423219820Sjeffstatic int ucma_destroy_kern_id(int fd, uint32_t handle) 424219820Sjeff{ 425219820Sjeff struct ucma_abi_destroy_id_resp *resp; 426219820Sjeff struct ucma_abi_destroy_id *cmd; 427219820Sjeff void *msg; 428219820Sjeff int ret, size; 429219820Sjeff 430219820Sjeff CMA_CREATE_MSG_CMD_RESP(msg, cmd, resp, UCMA_CMD_DESTROY_ID, size); 431219820Sjeff cmd->id = handle; 432219820Sjeff 433219820Sjeff ret = write(fd, msg, size); 434219820Sjeff if (ret != size) 435219820Sjeff return (ret >= 0) ? ERR(ECONNREFUSED) : -1; 436219820Sjeff 437219820Sjeff VALGRIND_MAKE_MEM_DEFINED(resp, sizeof *resp); 438219820Sjeff 439219820Sjeff return resp->events_reported; 440219820Sjeff} 441219820Sjeff 442219820Sjeffint rdma_destroy_id(struct rdma_cm_id *id) 443219820Sjeff{ 444219820Sjeff struct cma_id_private *id_priv; 445219820Sjeff int ret; 446219820Sjeff 447219820Sjeff id_priv = container_of(id, struct cma_id_private, id); 448219820Sjeff ret = ucma_destroy_kern_id(id->channel->fd, id_priv->handle); 449219820Sjeff if (ret < 0) 450219820Sjeff return ret; 451219820Sjeff 452219820Sjeff pthread_mutex_lock(&id_priv->mut); 453219820Sjeff while (id_priv->events_completed < ret) 454219820Sjeff pthread_cond_wait(&id_priv->cond, &id_priv->mut); 455219820Sjeff pthread_mutex_unlock(&id_priv->mut); 456219820Sjeff 457219820Sjeff ucma_free_id(id_priv); 458219820Sjeff return 0; 459219820Sjeff} 460219820Sjeff 461219820Sjeffstatic int ucma_addrlen(struct sockaddr *addr) 462219820Sjeff{ 463219820Sjeff if (!addr) 464219820Sjeff return 0; 465219820Sjeff 466219820Sjeff switch (addr->sa_family) { 467219820Sjeff case PF_INET: 468219820Sjeff return sizeof(struct sockaddr_in); 469219820Sjeff case PF_INET6: 470219820Sjeff return sizeof(struct sockaddr_in6); 471219820Sjeff default: 472219820Sjeff return 0; 473219820Sjeff } 474219820Sjeff} 475219820Sjeff 476219820Sjeffstatic int ucma_query_route(struct rdma_cm_id *id) 477219820Sjeff{ 478219820Sjeff struct ucma_abi_query_route_resp *resp; 479219820Sjeff struct ucma_abi_query_route *cmd; 480219820Sjeff struct cma_id_private *id_priv; 481219820Sjeff void *msg; 482219820Sjeff int ret, size, i; 483219820Sjeff 484219820Sjeff CMA_CREATE_MSG_CMD_RESP(msg, cmd, resp, UCMA_CMD_QUERY_ROUTE, size); 485219820Sjeff id_priv = container_of(id, struct cma_id_private, id); 486219820Sjeff cmd->id = id_priv->handle; 487219820Sjeff 488219820Sjeff ret = write(id->channel->fd, msg, size); 489219820Sjeff if (ret != size) 490219820Sjeff return (ret >= 0) ? ERR(ECONNREFUSED) : -1; 491219820Sjeff 492219820Sjeff VALGRIND_MAKE_MEM_DEFINED(resp, sizeof *resp); 493219820Sjeff 494219820Sjeff if (resp->num_paths) { 495219820Sjeff id->route.path_rec = malloc(sizeof *id->route.path_rec * 496219820Sjeff resp->num_paths); 497219820Sjeff if (!id->route.path_rec) 498219820Sjeff return ERR(ENOMEM); 499219820Sjeff 500219820Sjeff id->route.num_paths = resp->num_paths; 501219820Sjeff for (i = 0; i < resp->num_paths; i++) 502219820Sjeff ibv_copy_path_rec_from_kern(&id->route.path_rec[i], 503219820Sjeff &resp->ib_route[i]); 504219820Sjeff } 505219820Sjeff 506219820Sjeff memcpy(id->route.addr.addr.ibaddr.sgid.raw, resp->ib_route[0].sgid, 507219820Sjeff sizeof id->route.addr.addr.ibaddr.sgid); 508219820Sjeff memcpy(id->route.addr.addr.ibaddr.dgid.raw, resp->ib_route[0].dgid, 509219820Sjeff sizeof id->route.addr.addr.ibaddr.dgid); 510219820Sjeff id->route.addr.addr.ibaddr.pkey = resp->ib_route[0].pkey; 511219820Sjeff memcpy(&id->route.addr.src_addr, &resp->src_addr, 512219820Sjeff sizeof resp->src_addr); 513219820Sjeff memcpy(&id->route.addr.dst_addr, &resp->dst_addr, 514219820Sjeff sizeof resp->dst_addr); 515219820Sjeff 516219820Sjeff if (!id_priv->cma_dev && resp->node_guid) { 517219820Sjeff ret = ucma_get_device(id_priv, resp->node_guid); 518219820Sjeff if (ret) 519219820Sjeff return ret; 520219820Sjeff id_priv->id.port_num = resp->port_num; 521219820Sjeff } 522219820Sjeff 523219820Sjeff return 0; 524219820Sjeff} 525219820Sjeff 526219820Sjeffint rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) 527219820Sjeff{ 528219820Sjeff struct ucma_abi_bind_addr *cmd; 529219820Sjeff struct cma_id_private *id_priv; 530219820Sjeff void *msg; 531219820Sjeff int ret, size, addrlen; 532219820Sjeff 533219820Sjeff addrlen = ucma_addrlen(addr); 534219820Sjeff if (!addrlen) 535219820Sjeff return ERR(EINVAL); 536219820Sjeff 537219820Sjeff CMA_CREATE_MSG_CMD(msg, cmd, UCMA_CMD_BIND_ADDR, size); 538219820Sjeff id_priv = container_of(id, struct cma_id_private, id); 539219820Sjeff cmd->id = id_priv->handle; 540219820Sjeff memcpy(&cmd->addr, addr, addrlen); 541219820Sjeff 542219820Sjeff ret = write(id->channel->fd, msg, size); 543219820Sjeff if (ret != size) 544219820Sjeff return (ret >= 0) ? ERR(ECONNREFUSED) : -1; 545219820Sjeff 546219820Sjeff return ucma_query_route(id); 547219820Sjeff} 548219820Sjeff 549219820Sjeffint rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, 550219820Sjeff struct sockaddr *dst_addr, int timeout_ms) 551219820Sjeff{ 552219820Sjeff struct ucma_abi_resolve_addr *cmd; 553219820Sjeff struct cma_id_private *id_priv; 554219820Sjeff void *msg; 555219820Sjeff int ret, size, daddrlen; 556219820Sjeff 557219820Sjeff daddrlen = ucma_addrlen(dst_addr); 558219820Sjeff if (!daddrlen) 559219820Sjeff return ERR(EINVAL); 560219820Sjeff 561219820Sjeff CMA_CREATE_MSG_CMD(msg, cmd, UCMA_CMD_RESOLVE_ADDR, size); 562219820Sjeff id_priv = container_of(id, struct cma_id_private, id); 563219820Sjeff cmd->id = id_priv->handle; 564219820Sjeff if (src_addr) 565219820Sjeff memcpy(&cmd->src_addr, src_addr, ucma_addrlen(src_addr)); 566219820Sjeff memcpy(&cmd->dst_addr, dst_addr, daddrlen); 567219820Sjeff cmd->timeout_ms = timeout_ms; 568219820Sjeff 569219820Sjeff ret = write(id->channel->fd, msg, size); 570219820Sjeff if (ret != size) 571219820Sjeff return (ret >= 0) ? ERR(ECONNREFUSED) : -1; 572219820Sjeff 573219820Sjeff memcpy(&id->route.addr.dst_addr, dst_addr, daddrlen); 574219820Sjeff return 0; 575219820Sjeff} 576219820Sjeff 577219820Sjeffint rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms) 578219820Sjeff{ 579219820Sjeff struct ucma_abi_resolve_route *cmd; 580219820Sjeff struct cma_id_private *id_priv; 581219820Sjeff void *msg; 582219820Sjeff int ret, size; 583219820Sjeff 584219820Sjeff CMA_CREATE_MSG_CMD(msg, cmd, UCMA_CMD_RESOLVE_ROUTE, size); 585219820Sjeff id_priv = container_of(id, struct cma_id_private, id); 586219820Sjeff cmd->id = id_priv->handle; 587219820Sjeff cmd->timeout_ms = timeout_ms; 588219820Sjeff 589219820Sjeff ret = write(id->channel->fd, msg, size); 590219820Sjeff if (ret != size) 591219820Sjeff return (ret >= 0) ? ERR(ECONNREFUSED) : -1; 592219820Sjeff 593219820Sjeff return 0; 594219820Sjeff} 595219820Sjeff 596219820Sjeffstatic int ucma_is_ud_ps(enum rdma_port_space ps) 597219820Sjeff{ 598219820Sjeff return (ps == RDMA_PS_UDP || ps == RDMA_PS_IPOIB); 599219820Sjeff} 600219820Sjeff 601219820Sjeffstatic int rdma_init_qp_attr(struct rdma_cm_id *id, struct ibv_qp_attr *qp_attr, 602219820Sjeff int *qp_attr_mask) 603219820Sjeff{ 604219820Sjeff struct ucma_abi_init_qp_attr *cmd; 605219820Sjeff struct ibv_kern_qp_attr *resp; 606219820Sjeff struct cma_id_private *id_priv; 607219820Sjeff void *msg; 608219820Sjeff int ret, size; 609219820Sjeff 610219820Sjeff CMA_CREATE_MSG_CMD_RESP(msg, cmd, resp, UCMA_CMD_INIT_QP_ATTR, size); 611219820Sjeff id_priv = container_of(id, struct cma_id_private, id); 612219820Sjeff cmd->id = id_priv->handle; 613219820Sjeff cmd->qp_state = qp_attr->qp_state; 614219820Sjeff 615219820Sjeff ret = write(id->channel->fd, msg, size); 616219820Sjeff if (ret != size) 617219820Sjeff return (ret >= 0) ? ERR(ECONNREFUSED) : -1; 618219820Sjeff 619219820Sjeff VALGRIND_MAKE_MEM_DEFINED(resp, sizeof *resp); 620219820Sjeff 621219820Sjeff ibv_copy_qp_attr_from_kern(qp_attr, resp); 622219820Sjeff *qp_attr_mask = resp->qp_attr_mask; 623219820Sjeff return 0; 624219820Sjeff} 625219820Sjeff 626219820Sjeffstatic int ucma_modify_qp_rtr(struct rdma_cm_id *id, 627219820Sjeff struct rdma_conn_param *conn_param) 628219820Sjeff{ 629219820Sjeff struct ibv_qp_attr qp_attr; 630219820Sjeff int qp_attr_mask, ret; 631219820Sjeff 632219820Sjeff if (!id->qp) 633219820Sjeff return ERR(EINVAL); 634219820Sjeff 635219820Sjeff /* Need to update QP attributes from default values. */ 636219820Sjeff qp_attr.qp_state = IBV_QPS_INIT; 637219820Sjeff ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask); 638219820Sjeff if (ret) 639219820Sjeff return ret; 640219820Sjeff 641219820Sjeff ret = ibv_modify_qp(id->qp, &qp_attr, qp_attr_mask); 642219820Sjeff if (ret) 643219820Sjeff return ret; 644219820Sjeff 645219820Sjeff qp_attr.qp_state = IBV_QPS_RTR; 646219820Sjeff ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask); 647219820Sjeff if (ret) 648219820Sjeff return ret; 649219820Sjeff 650219820Sjeff if (conn_param) 651219820Sjeff qp_attr.max_dest_rd_atomic = conn_param->responder_resources; 652219820Sjeff return ibv_modify_qp(id->qp, &qp_attr, qp_attr_mask); 653219820Sjeff} 654219820Sjeff 655219820Sjeffstatic int ucma_modify_qp_rts(struct rdma_cm_id *id) 656219820Sjeff{ 657219820Sjeff struct ibv_qp_attr qp_attr; 658219820Sjeff int qp_attr_mask, ret; 659219820Sjeff 660219820Sjeff qp_attr.qp_state = IBV_QPS_RTS; 661219820Sjeff ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask); 662219820Sjeff if (ret) 663219820Sjeff return ret; 664219820Sjeff 665219820Sjeff return ibv_modify_qp(id->qp, &qp_attr, qp_attr_mask); 666219820Sjeff} 667219820Sjeff 668219820Sjeffstatic int ucma_modify_qp_sqd(struct rdma_cm_id *id) 669219820Sjeff{ 670219820Sjeff struct ibv_qp_attr qp_attr; 671219820Sjeff 672219820Sjeff if (!id->qp) 673219820Sjeff return 0; 674219820Sjeff 675219820Sjeff qp_attr.qp_state = IBV_QPS_SQD; 676219820Sjeff return ibv_modify_qp(id->qp, &qp_attr, IBV_QP_STATE); 677219820Sjeff} 678219820Sjeff 679219820Sjeffstatic int ucma_modify_qp_err(struct rdma_cm_id *id) 680219820Sjeff{ 681219820Sjeff struct ibv_qp_attr qp_attr; 682219820Sjeff 683219820Sjeff if (!id->qp) 684219820Sjeff return 0; 685219820Sjeff 686219820Sjeff qp_attr.qp_state = IBV_QPS_ERR; 687219820Sjeff return ibv_modify_qp(id->qp, &qp_attr, IBV_QP_STATE); 688219820Sjeff} 689219820Sjeff 690219820Sjeffstatic int ucma_find_pkey(struct cma_device *cma_dev, uint8_t port_num, 691219820Sjeff uint16_t pkey, uint16_t *pkey_index) 692219820Sjeff{ 693219820Sjeff int ret, i; 694219820Sjeff uint16_t chk_pkey; 695219820Sjeff 696219820Sjeff for (i = 0, ret = 0; !ret; i++) { 697219820Sjeff ret = ibv_query_pkey(cma_dev->verbs, port_num, i, &chk_pkey); 698219820Sjeff if (!ret && pkey == chk_pkey) { 699219820Sjeff *pkey_index = (uint16_t) i; 700219820Sjeff return 0; 701219820Sjeff } 702219820Sjeff } 703219820Sjeff return ERR(EINVAL); 704219820Sjeff} 705219820Sjeff 706219820Sjeffstatic int ucma_init_conn_qp3(struct cma_id_private *id_priv, struct ibv_qp *qp) 707219820Sjeff{ 708219820Sjeff struct ibv_qp_attr qp_attr; 709219820Sjeff int ret; 710219820Sjeff 711219820Sjeff ret = ucma_find_pkey(id_priv->cma_dev, id_priv->id.port_num, 712219820Sjeff id_priv->id.route.addr.addr.ibaddr.pkey, 713219820Sjeff &qp_attr.pkey_index); 714219820Sjeff if (ret) 715219820Sjeff return ret; 716219820Sjeff 717219820Sjeff qp_attr.port_num = id_priv->id.port_num; 718219820Sjeff qp_attr.qp_state = IBV_QPS_INIT; 719219820Sjeff qp_attr.qp_access_flags = 0; 720219820Sjeff 721219820Sjeff return ibv_modify_qp(qp, &qp_attr, IBV_QP_STATE | IBV_QP_ACCESS_FLAGS | 722219820Sjeff IBV_QP_PKEY_INDEX | IBV_QP_PORT); 723219820Sjeff} 724219820Sjeff 725219820Sjeffstatic int ucma_init_conn_qp(struct cma_id_private *id_priv, struct ibv_qp *qp) 726219820Sjeff{ 727219820Sjeff struct ibv_qp_attr qp_attr; 728219820Sjeff int qp_attr_mask, ret; 729219820Sjeff 730219820Sjeff if (abi_ver == 3) 731219820Sjeff return ucma_init_conn_qp3(id_priv, qp); 732219820Sjeff 733219820Sjeff qp_attr.qp_state = IBV_QPS_INIT; 734219820Sjeff ret = rdma_init_qp_attr(&id_priv->id, &qp_attr, &qp_attr_mask); 735219820Sjeff if (ret) 736219820Sjeff return ret; 737219820Sjeff 738219820Sjeff return ibv_modify_qp(qp, &qp_attr, qp_attr_mask); 739219820Sjeff} 740219820Sjeff 741219820Sjeffstatic int ucma_init_ud_qp3(struct cma_id_private *id_priv, struct ibv_qp *qp) 742219820Sjeff{ 743219820Sjeff struct ibv_qp_attr qp_attr; 744219820Sjeff int ret; 745219820Sjeff 746219820Sjeff ret = ucma_find_pkey(id_priv->cma_dev, id_priv->id.port_num, 747219820Sjeff id_priv->id.route.addr.addr.ibaddr.pkey, 748219820Sjeff &qp_attr.pkey_index); 749219820Sjeff if (ret) 750219820Sjeff return ret; 751219820Sjeff 752219820Sjeff qp_attr.port_num = id_priv->id.port_num; 753219820Sjeff qp_attr.qp_state = IBV_QPS_INIT; 754219820Sjeff qp_attr.qkey = RDMA_UDP_QKEY; 755219820Sjeff 756219820Sjeff ret = ibv_modify_qp(qp, &qp_attr, IBV_QP_STATE | IBV_QP_QKEY | 757219820Sjeff IBV_QP_PKEY_INDEX | IBV_QP_PORT); 758219820Sjeff if (ret) 759219820Sjeff return ret; 760219820Sjeff 761219820Sjeff qp_attr.qp_state = IBV_QPS_RTR; 762219820Sjeff ret = ibv_modify_qp(qp, &qp_attr, IBV_QP_STATE); 763219820Sjeff if (ret) 764219820Sjeff return ret; 765219820Sjeff 766219820Sjeff qp_attr.qp_state = IBV_QPS_RTS; 767219820Sjeff qp_attr.sq_psn = 0; 768219820Sjeff return ibv_modify_qp(qp, &qp_attr, IBV_QP_STATE | IBV_QP_SQ_PSN); 769219820Sjeff} 770219820Sjeff 771219820Sjeffstatic int ucma_init_ud_qp(struct cma_id_private *id_priv, struct ibv_qp *qp) 772219820Sjeff{ 773219820Sjeff struct ibv_qp_attr qp_attr; 774219820Sjeff int qp_attr_mask, ret; 775219820Sjeff 776219820Sjeff if (abi_ver == 3) 777219820Sjeff return ucma_init_ud_qp3(id_priv, qp); 778219820Sjeff 779219820Sjeff qp_attr.qp_state = IBV_QPS_INIT; 780219820Sjeff ret = rdma_init_qp_attr(&id_priv->id, &qp_attr, &qp_attr_mask); 781219820Sjeff if (ret) 782219820Sjeff return ret; 783219820Sjeff 784219820Sjeff ret = ibv_modify_qp(qp, &qp_attr, qp_attr_mask); 785219820Sjeff if (ret) 786219820Sjeff return ret; 787219820Sjeff 788219820Sjeff qp_attr.qp_state = IBV_QPS_RTR; 789219820Sjeff ret = ibv_modify_qp(qp, &qp_attr, IBV_QP_STATE); 790219820Sjeff if (ret) 791219820Sjeff return ret; 792219820Sjeff 793219820Sjeff qp_attr.qp_state = IBV_QPS_RTS; 794219820Sjeff qp_attr.sq_psn = 0; 795219820Sjeff return ibv_modify_qp(qp, &qp_attr, IBV_QP_STATE | IBV_QP_SQ_PSN); 796219820Sjeff} 797219820Sjeff 798219820Sjeffint rdma_create_qp(struct rdma_cm_id *id, struct ibv_pd *pd, 799219820Sjeff struct ibv_qp_init_attr *qp_init_attr) 800219820Sjeff{ 801219820Sjeff struct cma_id_private *id_priv; 802219820Sjeff struct ibv_qp *qp; 803219820Sjeff int ret; 804219820Sjeff 805219820Sjeff id_priv = container_of(id, struct cma_id_private, id); 806219820Sjeff if (id->verbs != pd->context) 807219820Sjeff return ERR(EINVAL); 808219820Sjeff 809219820Sjeff qp = ibv_create_qp(pd, qp_init_attr); 810219820Sjeff if (!qp) 811219820Sjeff return ERR(ENOMEM); 812219820Sjeff 813219820Sjeff if (ucma_is_ud_ps(id->ps)) 814219820Sjeff ret = ucma_init_ud_qp(id_priv, qp); 815219820Sjeff else 816219820Sjeff ret = ucma_init_conn_qp(id_priv, qp); 817219820Sjeff if (ret) 818219820Sjeff goto err; 819219820Sjeff 820219820Sjeff id->qp = qp; 821219820Sjeff return 0; 822219820Sjefferr: 823219820Sjeff ibv_destroy_qp(qp); 824219820Sjeff return ret; 825219820Sjeff} 826219820Sjeff 827219820Sjeffvoid rdma_destroy_qp(struct rdma_cm_id *id) 828219820Sjeff{ 829219820Sjeff ibv_destroy_qp(id->qp); 830219820Sjeff} 831219820Sjeff 832219820Sjeffstatic int ucma_valid_param(struct cma_id_private *id_priv, 833219820Sjeff struct rdma_conn_param *conn_param) 834219820Sjeff{ 835219820Sjeff if (id_priv->id.ps != RDMA_PS_TCP) 836219820Sjeff return 0; 837219820Sjeff 838219820Sjeff if ((conn_param->responder_resources > 839219820Sjeff id_priv->cma_dev->max_responder_resources) || 840219820Sjeff (conn_param->initiator_depth > 841219820Sjeff id_priv->cma_dev->max_initiator_depth)) 842219820Sjeff return ERR(EINVAL); 843219820Sjeff 844219820Sjeff return 0; 845219820Sjeff} 846219820Sjeff 847219820Sjeffstatic void ucma_copy_conn_param_to_kern(struct ucma_abi_conn_param *dst, 848219820Sjeff struct rdma_conn_param *src, 849219820Sjeff uint32_t qp_num, uint8_t srq) 850219820Sjeff{ 851219820Sjeff dst->qp_num = qp_num; 852219820Sjeff dst->srq = srq; 853219820Sjeff dst->responder_resources = src->responder_resources; 854219820Sjeff dst->initiator_depth = src->initiator_depth; 855219820Sjeff dst->flow_control = src->flow_control; 856219820Sjeff dst->retry_count = src->retry_count; 857219820Sjeff dst->rnr_retry_count = src->rnr_retry_count; 858219820Sjeff dst->valid = 1; 859219820Sjeff 860219820Sjeff if (src->private_data && src->private_data_len) { 861219820Sjeff memcpy(dst->private_data, src->private_data, 862219820Sjeff src->private_data_len); 863219820Sjeff dst->private_data_len = src->private_data_len; 864219820Sjeff } 865219820Sjeff} 866219820Sjeff 867219820Sjeffint rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) 868219820Sjeff{ 869219820Sjeff struct ucma_abi_connect *cmd; 870219820Sjeff struct cma_id_private *id_priv; 871219820Sjeff void *msg; 872219820Sjeff int ret, size; 873219820Sjeff 874219820Sjeff id_priv = container_of(id, struct cma_id_private, id); 875219820Sjeff ret = ucma_valid_param(id_priv, conn_param); 876219820Sjeff if (ret) 877219820Sjeff return ret; 878219820Sjeff 879219820Sjeff CMA_CREATE_MSG_CMD(msg, cmd, UCMA_CMD_CONNECT, size); 880219820Sjeff cmd->id = id_priv->handle; 881219820Sjeff if (id->qp) 882219820Sjeff ucma_copy_conn_param_to_kern(&cmd->conn_param, conn_param, 883219820Sjeff id->qp->qp_num, 884219820Sjeff (id->qp->srq != NULL)); 885219820Sjeff else 886219820Sjeff ucma_copy_conn_param_to_kern(&cmd->conn_param, conn_param, 887219820Sjeff conn_param->qp_num, 888219820Sjeff conn_param->srq); 889219820Sjeff 890219820Sjeff ret = write(id->channel->fd, msg, size); 891219820Sjeff if (ret != size) 892219820Sjeff return (ret >= 0) ? ERR(ECONNREFUSED) : -1; 893219820Sjeff 894219820Sjeff return 0; 895219820Sjeff} 896219820Sjeff 897219820Sjeffint rdma_listen(struct rdma_cm_id *id, int backlog) 898219820Sjeff{ 899219820Sjeff struct ucma_abi_listen *cmd; 900219820Sjeff struct cma_id_private *id_priv; 901219820Sjeff void *msg; 902219820Sjeff int ret, size; 903219820Sjeff 904219820Sjeff CMA_CREATE_MSG_CMD(msg, cmd, UCMA_CMD_LISTEN, size); 905219820Sjeff id_priv = container_of(id, struct cma_id_private, id); 906219820Sjeff cmd->id = id_priv->handle; 907219820Sjeff cmd->backlog = backlog; 908219820Sjeff 909219820Sjeff ret = write(id->channel->fd, msg, size); 910219820Sjeff if (ret != size) 911219820Sjeff return (ret >= 0) ? ERR(ECONNREFUSED) : -1; 912219820Sjeff 913219820Sjeff return ucma_query_route(id); 914219820Sjeff} 915219820Sjeff 916219820Sjeffint rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) 917219820Sjeff{ 918219820Sjeff struct ucma_abi_accept *cmd; 919219820Sjeff struct cma_id_private *id_priv; 920219820Sjeff void *msg; 921219820Sjeff int ret, size; 922219820Sjeff 923219820Sjeff id_priv = container_of(id, struct cma_id_private, id); 924219820Sjeff ret = ucma_valid_param(id_priv, conn_param); 925219820Sjeff if (ret) 926219820Sjeff return ret; 927219820Sjeff 928219820Sjeff if (!ucma_is_ud_ps(id->ps)) { 929219820Sjeff ret = ucma_modify_qp_rtr(id, conn_param); 930219820Sjeff if (ret) 931219820Sjeff return ret; 932219820Sjeff } 933219820Sjeff 934219820Sjeff CMA_CREATE_MSG_CMD(msg, cmd, UCMA_CMD_ACCEPT, size); 935219820Sjeff cmd->id = id_priv->handle; 936219820Sjeff cmd->uid = (uintptr_t) id_priv; 937219820Sjeff if (id->qp) 938219820Sjeff ucma_copy_conn_param_to_kern(&cmd->conn_param, conn_param, 939219820Sjeff id->qp->qp_num, 940219820Sjeff (id->qp->srq != NULL)); 941219820Sjeff else 942219820Sjeff ucma_copy_conn_param_to_kern(&cmd->conn_param, conn_param, 943219820Sjeff conn_param->qp_num, 944219820Sjeff conn_param->srq); 945219820Sjeff 946219820Sjeff ret = write(id->channel->fd, msg, size); 947219820Sjeff if (ret != size) { 948219820Sjeff ucma_modify_qp_err(id); 949219820Sjeff return (ret >= 0) ? ERR(ECONNREFUSED) : -1; 950219820Sjeff } 951219820Sjeff 952219820Sjeff return 0; 953219820Sjeff} 954219820Sjeff 955219820Sjeffint rdma_reject(struct rdma_cm_id *id, const void *private_data, 956219820Sjeff uint8_t private_data_len) 957219820Sjeff{ 958219820Sjeff struct ucma_abi_reject *cmd; 959219820Sjeff struct cma_id_private *id_priv; 960219820Sjeff void *msg; 961219820Sjeff int ret, size; 962219820Sjeff 963219820Sjeff CMA_CREATE_MSG_CMD(msg, cmd, UCMA_CMD_REJECT, size); 964219820Sjeff 965219820Sjeff id_priv = container_of(id, struct cma_id_private, id); 966219820Sjeff cmd->id = id_priv->handle; 967219820Sjeff if (private_data && private_data_len) { 968219820Sjeff memcpy(cmd->private_data, private_data, private_data_len); 969219820Sjeff cmd->private_data_len = private_data_len; 970219820Sjeff } else 971219820Sjeff cmd->private_data_len = 0; 972219820Sjeff 973219820Sjeff ret = write(id->channel->fd, msg, size); 974219820Sjeff if (ret != size) 975219820Sjeff return (ret >= 0) ? ERR(ECONNREFUSED) : -1; 976219820Sjeff 977219820Sjeff return 0; 978219820Sjeff} 979219820Sjeff 980219820Sjeffint rdma_notify(struct rdma_cm_id *id, enum ibv_event_type event) 981219820Sjeff{ 982219820Sjeff struct ucma_abi_notify *cmd; 983219820Sjeff struct cma_id_private *id_priv; 984219820Sjeff void *msg; 985219820Sjeff int ret, size; 986219820Sjeff 987219820Sjeff CMA_CREATE_MSG_CMD(msg, cmd, UCMA_CMD_NOTIFY, size); 988219820Sjeff 989219820Sjeff id_priv = container_of(id, struct cma_id_private, id); 990219820Sjeff cmd->id = id_priv->handle; 991219820Sjeff cmd->event = event; 992219820Sjeff ret = write(id->channel->fd, msg, size); 993219820Sjeff if (ret != size) 994219820Sjeff return (ret >= 0) ? ERR(ECONNREFUSED) : -1; 995219820Sjeff 996219820Sjeff return 0; 997219820Sjeff} 998219820Sjeff 999219820Sjeffint rdma_disconnect(struct rdma_cm_id *id) 1000219820Sjeff{ 1001219820Sjeff struct ucma_abi_disconnect *cmd; 1002219820Sjeff struct cma_id_private *id_priv; 1003219820Sjeff void *msg; 1004219820Sjeff int ret, size; 1005219820Sjeff 1006219820Sjeff switch (id->verbs->device->transport_type) { 1007219820Sjeff case IBV_TRANSPORT_IB: 1008219820Sjeff ret = ucma_modify_qp_err(id); 1009219820Sjeff break; 1010219820Sjeff case IBV_TRANSPORT_IWARP: 1011219820Sjeff ret = ucma_modify_qp_sqd(id); 1012219820Sjeff break; 1013219820Sjeff default: 1014219820Sjeff ret = ERR(EINVAL); 1015219820Sjeff } 1016219820Sjeff if (ret) 1017219820Sjeff return ret; 1018219820Sjeff 1019219820Sjeff CMA_CREATE_MSG_CMD(msg, cmd, UCMA_CMD_DISCONNECT, size); 1020219820Sjeff id_priv = container_of(id, struct cma_id_private, id); 1021219820Sjeff cmd->id = id_priv->handle; 1022219820Sjeff 1023219820Sjeff ret = write(id->channel->fd, msg, size); 1024219820Sjeff if (ret != size) 1025219820Sjeff return (ret >= 0) ? ERR(ECONNREFUSED) : -1; 1026219820Sjeff 1027219820Sjeff return 0; 1028219820Sjeff} 1029219820Sjeff 1030219820Sjeffint rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr, 1031219820Sjeff void *context) 1032219820Sjeff{ 1033219820Sjeff struct ucma_abi_join_mcast *cmd; 1034219820Sjeff struct ucma_abi_create_id_resp *resp; 1035219820Sjeff struct cma_id_private *id_priv; 1036219820Sjeff struct cma_multicast *mc, **pos; 1037219820Sjeff void *msg; 1038219820Sjeff int ret, size, addrlen; 1039219820Sjeff 1040219820Sjeff id_priv = container_of(id, struct cma_id_private, id); 1041219820Sjeff addrlen = ucma_addrlen(addr); 1042219820Sjeff if (!addrlen) 1043219820Sjeff return ERR(EINVAL); 1044219820Sjeff 1045219820Sjeff mc = malloc(sizeof *mc); 1046219820Sjeff if (!mc) 1047219820Sjeff return ERR(ENOMEM); 1048219820Sjeff 1049219820Sjeff memset(mc, 0, sizeof *mc); 1050219820Sjeff mc->context = context; 1051219820Sjeff mc->id_priv = id_priv; 1052219820Sjeff memcpy(&mc->addr, addr, addrlen); 1053219820Sjeff if (pthread_cond_init(&mc->cond, NULL)) { 1054219820Sjeff ret = -1; 1055219820Sjeff goto err1; 1056219820Sjeff } 1057219820Sjeff 1058219820Sjeff pthread_mutex_lock(&id_priv->mut); 1059219820Sjeff mc->next = id_priv->mc_list; 1060219820Sjeff id_priv->mc_list = mc; 1061219820Sjeff pthread_mutex_unlock(&id_priv->mut); 1062219820Sjeff 1063219820Sjeff CMA_CREATE_MSG_CMD_RESP(msg, cmd, resp, UCMA_CMD_JOIN_MCAST, size); 1064219820Sjeff cmd->id = id_priv->handle; 1065219820Sjeff memcpy(&cmd->addr, addr, addrlen); 1066219820Sjeff cmd->uid = (uintptr_t) mc; 1067219820Sjeff 1068219820Sjeff ret = write(id->channel->fd, msg, size); 1069219820Sjeff if (ret != size) { 1070219820Sjeff ret = (ret >= 0) ? ERR(ECONNREFUSED) : -1; 1071219820Sjeff goto err2; 1072219820Sjeff } 1073219820Sjeff 1074219820Sjeff VALGRIND_MAKE_MEM_DEFINED(resp, sizeof *resp); 1075219820Sjeff 1076219820Sjeff mc->handle = resp->id; 1077219820Sjeff return 0; 1078219820Sjefferr2: 1079219820Sjeff pthread_mutex_lock(&id_priv->mut); 1080219820Sjeff for (pos = &id_priv->mc_list; *pos != mc; pos = &(*pos)->next) 1081219820Sjeff ; 1082219820Sjeff *pos = mc->next; 1083219820Sjeff pthread_mutex_unlock(&id_priv->mut); 1084219820Sjefferr1: 1085219820Sjeff free(mc); 1086219820Sjeff return ret; 1087219820Sjeff} 1088219820Sjeff 1089219820Sjeffint rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr) 1090219820Sjeff{ 1091219820Sjeff struct ucma_abi_destroy_id *cmd; 1092219820Sjeff struct ucma_abi_destroy_id_resp *resp; 1093219820Sjeff struct cma_id_private *id_priv; 1094219820Sjeff struct cma_multicast *mc, **pos; 1095219820Sjeff void *msg; 1096219820Sjeff int ret, size, addrlen; 1097219820Sjeff 1098219820Sjeff addrlen = ucma_addrlen(addr); 1099219820Sjeff if (!addrlen) 1100219820Sjeff return ERR(EINVAL); 1101219820Sjeff 1102219820Sjeff id_priv = container_of(id, struct cma_id_private, id); 1103219820Sjeff pthread_mutex_lock(&id_priv->mut); 1104219820Sjeff for (pos = &id_priv->mc_list; *pos; pos = &(*pos)->next) 1105219820Sjeff if (!memcmp(&(*pos)->addr, addr, addrlen)) 1106219820Sjeff break; 1107219820Sjeff 1108219820Sjeff mc = *pos; 1109219820Sjeff if (*pos) 1110219820Sjeff *pos = mc->next; 1111219820Sjeff pthread_mutex_unlock(&id_priv->mut); 1112219820Sjeff if (!mc) 1113219820Sjeff return ERR(EADDRNOTAVAIL); 1114219820Sjeff 1115219820Sjeff if (id->qp) 1116219820Sjeff ibv_detach_mcast(id->qp, &mc->mgid, mc->mlid); 1117219820Sjeff 1118219820Sjeff CMA_CREATE_MSG_CMD_RESP(msg, cmd, resp, UCMA_CMD_LEAVE_MCAST, size); 1119219820Sjeff cmd->id = mc->handle; 1120219820Sjeff 1121219820Sjeff ret = write(id->channel->fd, msg, size); 1122219820Sjeff if (ret != size) { 1123219820Sjeff ret = (ret >= 0) ? ERR(ECONNREFUSED) : -1; 1124219820Sjeff goto free; 1125219820Sjeff } 1126219820Sjeff 1127219820Sjeff VALGRIND_MAKE_MEM_DEFINED(resp, sizeof *resp); 1128219820Sjeff 1129219820Sjeff pthread_mutex_lock(&id_priv->mut); 1130219820Sjeff while (mc->events_completed < resp->events_reported) 1131219820Sjeff pthread_cond_wait(&mc->cond, &id_priv->mut); 1132219820Sjeff pthread_mutex_unlock(&id_priv->mut); 1133219820Sjeff 1134219820Sjeff ret = 0; 1135219820Sjefffree: 1136219820Sjeff free(mc); 1137219820Sjeff return ret; 1138219820Sjeff} 1139219820Sjeff 1140219820Sjeffstatic void ucma_complete_event(struct cma_id_private *id_priv) 1141219820Sjeff{ 1142219820Sjeff pthread_mutex_lock(&id_priv->mut); 1143219820Sjeff id_priv->events_completed++; 1144219820Sjeff pthread_cond_signal(&id_priv->cond); 1145219820Sjeff pthread_mutex_unlock(&id_priv->mut); 1146219820Sjeff} 1147219820Sjeff 1148219820Sjeffstatic void ucma_complete_mc_event(struct cma_multicast *mc) 1149219820Sjeff{ 1150219820Sjeff pthread_mutex_lock(&mc->id_priv->mut); 1151219820Sjeff mc->events_completed++; 1152219820Sjeff pthread_cond_signal(&mc->cond); 1153219820Sjeff mc->id_priv->events_completed++; 1154219820Sjeff pthread_cond_signal(&mc->id_priv->cond); 1155219820Sjeff pthread_mutex_unlock(&mc->id_priv->mut); 1156219820Sjeff} 1157219820Sjeff 1158219820Sjeffint rdma_ack_cm_event(struct rdma_cm_event *event) 1159219820Sjeff{ 1160219820Sjeff struct cma_event *evt; 1161219820Sjeff 1162219820Sjeff if (!event) 1163219820Sjeff return ERR(EINVAL); 1164219820Sjeff 1165219820Sjeff evt = container_of(event, struct cma_event, event); 1166219820Sjeff 1167219820Sjeff if (evt->mc) 1168219820Sjeff ucma_complete_mc_event(evt->mc); 1169219820Sjeff else 1170219820Sjeff ucma_complete_event(evt->id_priv); 1171219820Sjeff free(evt); 1172219820Sjeff return 0; 1173219820Sjeff} 1174219820Sjeff 1175219820Sjeffstatic int ucma_process_conn_req(struct cma_event *evt, 1176219820Sjeff uint32_t handle) 1177219820Sjeff{ 1178219820Sjeff struct cma_id_private *id_priv; 1179219820Sjeff int ret; 1180219820Sjeff 1181219820Sjeff id_priv = ucma_alloc_id(evt->id_priv->id.channel, 1182219820Sjeff evt->id_priv->id.context, evt->id_priv->id.ps); 1183219820Sjeff if (!id_priv) { 1184219820Sjeff ucma_destroy_kern_id(evt->id_priv->id.channel->fd, handle); 1185219820Sjeff ret = ERR(ENOMEM); 1186219820Sjeff goto err; 1187219820Sjeff } 1188219820Sjeff 1189219820Sjeff evt->event.listen_id = &evt->id_priv->id; 1190219820Sjeff evt->event.id = &id_priv->id; 1191219820Sjeff id_priv->handle = handle; 1192219820Sjeff 1193219820Sjeff ret = ucma_query_route(&id_priv->id); 1194219820Sjeff if (ret) { 1195219820Sjeff rdma_destroy_id(&id_priv->id); 1196219820Sjeff goto err; 1197219820Sjeff } 1198219820Sjeff 1199219820Sjeff return 0; 1200219820Sjefferr: 1201219820Sjeff ucma_complete_event(evt->id_priv); 1202219820Sjeff return ret; 1203219820Sjeff} 1204219820Sjeff 1205219820Sjeffstatic int ucma_process_conn_resp(struct cma_id_private *id_priv) 1206219820Sjeff{ 1207219820Sjeff struct ucma_abi_accept *cmd; 1208219820Sjeff void *msg; 1209219820Sjeff int ret, size; 1210219820Sjeff 1211219820Sjeff ret = ucma_modify_qp_rtr(&id_priv->id, NULL); 1212219820Sjeff if (ret) 1213219820Sjeff goto err; 1214219820Sjeff 1215219820Sjeff ret = ucma_modify_qp_rts(&id_priv->id); 1216219820Sjeff if (ret) 1217219820Sjeff goto err; 1218219820Sjeff 1219219820Sjeff CMA_CREATE_MSG_CMD(msg, cmd, UCMA_CMD_ACCEPT, size); 1220219820Sjeff cmd->id = id_priv->handle; 1221219820Sjeff 1222219820Sjeff ret = write(id_priv->id.channel->fd, msg, size); 1223219820Sjeff if (ret != size) { 1224219820Sjeff ret = (ret >= 0) ? ERR(ECONNREFUSED) : -1; 1225219820Sjeff goto err; 1226219820Sjeff } 1227219820Sjeff 1228219820Sjeff return 0; 1229219820Sjefferr: 1230219820Sjeff ucma_modify_qp_err(&id_priv->id); 1231219820Sjeff return ret; 1232219820Sjeff} 1233219820Sjeff 1234219820Sjeffstatic int ucma_process_establish(struct rdma_cm_id *id) 1235219820Sjeff{ 1236219820Sjeff int ret; 1237219820Sjeff 1238219820Sjeff ret = ucma_modify_qp_rts(id); 1239219820Sjeff if (ret) 1240219820Sjeff ucma_modify_qp_err(id); 1241219820Sjeff 1242219820Sjeff return ret; 1243219820Sjeff} 1244219820Sjeff 1245219820Sjeffstatic int ucma_process_join(struct cma_event *evt) 1246219820Sjeff{ 1247219820Sjeff evt->mc->mgid = evt->event.param.ud.ah_attr.grh.dgid; 1248219820Sjeff evt->mc->mlid = evt->event.param.ud.ah_attr.dlid; 1249219820Sjeff 1250219820Sjeff if (!evt->id_priv->id.qp) 1251219820Sjeff return 0; 1252219820Sjeff 1253219820Sjeff return ibv_attach_mcast(evt->id_priv->id.qp, &evt->mc->mgid, 1254219820Sjeff evt->mc->mlid); 1255219820Sjeff} 1256219820Sjeff 1257219820Sjeffstatic void ucma_copy_conn_event(struct cma_event *event, 1258219820Sjeff struct ucma_abi_conn_param *src) 1259219820Sjeff{ 1260219820Sjeff struct rdma_conn_param *dst = &event->event.param.conn; 1261219820Sjeff 1262219820Sjeff dst->private_data_len = src->private_data_len; 1263219820Sjeff if (src->private_data_len) { 1264219820Sjeff dst->private_data = &event->private_data; 1265219820Sjeff memcpy(&event->private_data, src->private_data, 1266219820Sjeff src->private_data_len); 1267219820Sjeff } 1268219820Sjeff 1269219820Sjeff dst->responder_resources = src->responder_resources; 1270219820Sjeff dst->initiator_depth = src->initiator_depth; 1271219820Sjeff dst->flow_control = src->flow_control; 1272219820Sjeff dst->retry_count = src->retry_count; 1273219820Sjeff dst->rnr_retry_count = src->rnr_retry_count; 1274219820Sjeff dst->srq = src->srq; 1275219820Sjeff dst->qp_num = src->qp_num; 1276219820Sjeff} 1277219820Sjeff 1278219820Sjeffstatic void ucma_copy_ud_event(struct cma_event *event, 1279219820Sjeff struct ucma_abi_ud_param *src) 1280219820Sjeff{ 1281219820Sjeff struct rdma_ud_param *dst = &event->event.param.ud; 1282219820Sjeff 1283219820Sjeff dst->private_data_len = src->private_data_len; 1284219820Sjeff if (src->private_data_len) { 1285219820Sjeff dst->private_data = &event->private_data; 1286219820Sjeff memcpy(&event->private_data, src->private_data, 1287219820Sjeff src->private_data_len); 1288219820Sjeff } 1289219820Sjeff 1290219820Sjeff ibv_copy_ah_attr_from_kern(&dst->ah_attr, &src->ah_attr); 1291219820Sjeff dst->qp_num = src->qp_num; 1292219820Sjeff dst->qkey = src->qkey; 1293219820Sjeff} 1294219820Sjeff 1295219820Sjeffint rdma_get_cm_event(struct rdma_event_channel *channel, 1296219820Sjeff struct rdma_cm_event **event) 1297219820Sjeff{ 1298219820Sjeff struct ucma_abi_event_resp *resp; 1299219820Sjeff struct ucma_abi_get_event *cmd; 1300219820Sjeff struct cma_event *evt; 1301219820Sjeff void *msg; 1302219820Sjeff int ret, size; 1303219820Sjeff 1304219820Sjeff ret = cma_dev_cnt ? 0 : ucma_init(); 1305219820Sjeff if (ret) 1306219820Sjeff return ret; 1307219820Sjeff 1308219820Sjeff if (!event) 1309219820Sjeff return ERR(EINVAL); 1310219820Sjeff 1311219820Sjeff evt = malloc(sizeof *evt); 1312219820Sjeff if (!evt) 1313219820Sjeff return ERR(ENOMEM); 1314219820Sjeff 1315219820Sjeffretry: 1316219820Sjeff memset(evt, 0, sizeof *evt); 1317219820Sjeff CMA_CREATE_MSG_CMD_RESP(msg, cmd, resp, UCMA_CMD_GET_EVENT, size); 1318219820Sjeff ret = write(channel->fd, msg, size); 1319219820Sjeff if (ret != size) { 1320219820Sjeff free(evt); 1321219820Sjeff return (ret >= 0) ? ERR(ECONNREFUSED) : -1; 1322219820Sjeff } 1323219820Sjeff 1324219820Sjeff VALGRIND_MAKE_MEM_DEFINED(resp, sizeof *resp); 1325219820Sjeff 1326219820Sjeff evt->event.event = resp->event; 1327219820Sjeff evt->id_priv = (void *) (uintptr_t) resp->uid; 1328219820Sjeff evt->event.id = &evt->id_priv->id; 1329219820Sjeff evt->event.status = resp->status; 1330219820Sjeff 1331219820Sjeff switch (resp->event) { 1332219820Sjeff case RDMA_CM_EVENT_ADDR_RESOLVED: 1333219820Sjeff evt->event.status = ucma_query_route(&evt->id_priv->id); 1334219820Sjeff if (evt->event.status) 1335219820Sjeff evt->event.event = RDMA_CM_EVENT_ADDR_ERROR; 1336219820Sjeff break; 1337219820Sjeff case RDMA_CM_EVENT_ROUTE_RESOLVED: 1338219820Sjeff evt->event.status = ucma_query_route(&evt->id_priv->id); 1339219820Sjeff if (evt->event.status) 1340219820Sjeff evt->event.event = RDMA_CM_EVENT_ROUTE_ERROR; 1341219820Sjeff break; 1342219820Sjeff case RDMA_CM_EVENT_CONNECT_REQUEST: 1343219820Sjeff evt->id_priv = (void *) (uintptr_t) resp->uid; 1344219820Sjeff if (ucma_is_ud_ps(evt->id_priv->id.ps)) 1345219820Sjeff ucma_copy_ud_event(evt, &resp->param.ud); 1346219820Sjeff else 1347219820Sjeff ucma_copy_conn_event(evt, &resp->param.conn); 1348219820Sjeff 1349219820Sjeff ret = ucma_process_conn_req(evt, resp->id); 1350219820Sjeff if (ret) 1351219820Sjeff goto retry; 1352219820Sjeff break; 1353219820Sjeff case RDMA_CM_EVENT_CONNECT_RESPONSE: 1354219820Sjeff ucma_copy_conn_event(evt, &resp->param.conn); 1355219820Sjeff evt->event.status = ucma_process_conn_resp(evt->id_priv); 1356219820Sjeff if (!evt->event.status) 1357219820Sjeff evt->event.event = RDMA_CM_EVENT_ESTABLISHED; 1358219820Sjeff else { 1359219820Sjeff evt->event.event = RDMA_CM_EVENT_CONNECT_ERROR; 1360219820Sjeff evt->id_priv->connect_error = 1; 1361219820Sjeff } 1362219820Sjeff break; 1363219820Sjeff case RDMA_CM_EVENT_ESTABLISHED: 1364219820Sjeff if (ucma_is_ud_ps(evt->id_priv->id.ps)) { 1365219820Sjeff ucma_copy_ud_event(evt, &resp->param.ud); 1366219820Sjeff break; 1367219820Sjeff } 1368219820Sjeff 1369219820Sjeff ucma_copy_conn_event(evt, &resp->param.conn); 1370219820Sjeff evt->event.status = ucma_process_establish(&evt->id_priv->id); 1371219820Sjeff if (evt->event.status) { 1372219820Sjeff evt->event.event = RDMA_CM_EVENT_CONNECT_ERROR; 1373219820Sjeff evt->id_priv->connect_error = 1; 1374219820Sjeff } 1375219820Sjeff break; 1376219820Sjeff case RDMA_CM_EVENT_REJECTED: 1377219820Sjeff if (evt->id_priv->connect_error) { 1378219820Sjeff ucma_complete_event(evt->id_priv); 1379219820Sjeff goto retry; 1380219820Sjeff } 1381219820Sjeff ucma_copy_conn_event(evt, &resp->param.conn); 1382219820Sjeff ucma_modify_qp_err(evt->event.id); 1383219820Sjeff break; 1384219820Sjeff case RDMA_CM_EVENT_DISCONNECTED: 1385219820Sjeff if (evt->id_priv->connect_error) { 1386219820Sjeff ucma_complete_event(evt->id_priv); 1387219820Sjeff goto retry; 1388219820Sjeff } 1389219820Sjeff ucma_copy_conn_event(evt, &resp->param.conn); 1390219820Sjeff break; 1391219820Sjeff case RDMA_CM_EVENT_MULTICAST_JOIN: 1392219820Sjeff evt->mc = (void *) (uintptr_t) resp->uid; 1393219820Sjeff evt->id_priv = evt->mc->id_priv; 1394219820Sjeff evt->event.id = &evt->id_priv->id; 1395219820Sjeff ucma_copy_ud_event(evt, &resp->param.ud); 1396219820Sjeff evt->event.param.ud.private_data = evt->mc->context; 1397219820Sjeff evt->event.status = ucma_process_join(evt); 1398219820Sjeff if (evt->event.status) 1399219820Sjeff evt->event.event = RDMA_CM_EVENT_MULTICAST_ERROR; 1400219820Sjeff break; 1401219820Sjeff case RDMA_CM_EVENT_MULTICAST_ERROR: 1402219820Sjeff evt->mc = (void *) (uintptr_t) resp->uid; 1403219820Sjeff evt->id_priv = evt->mc->id_priv; 1404219820Sjeff evt->event.id = &evt->id_priv->id; 1405219820Sjeff evt->event.param.ud.private_data = evt->mc->context; 1406219820Sjeff break; 1407219820Sjeff default: 1408219820Sjeff evt->id_priv = (void *) (uintptr_t) resp->uid; 1409219820Sjeff evt->event.id = &evt->id_priv->id; 1410219820Sjeff evt->event.status = resp->status; 1411219820Sjeff if (ucma_is_ud_ps(evt->id_priv->id.ps)) 1412219820Sjeff ucma_copy_ud_event(evt, &resp->param.ud); 1413219820Sjeff else 1414219820Sjeff ucma_copy_conn_event(evt, &resp->param.conn); 1415219820Sjeff break; 1416219820Sjeff } 1417219820Sjeff 1418219820Sjeff *event = &evt->event; 1419219820Sjeff return 0; 1420219820Sjeff} 1421219820Sjeff 1422219820Sjeffconst char *rdma_event_str(enum rdma_cm_event_type event) 1423219820Sjeff{ 1424219820Sjeff switch (event) { 1425219820Sjeff case RDMA_CM_EVENT_ADDR_RESOLVED: 1426219820Sjeff return "RDMA_CM_EVENT_ADDR_RESOLVED"; 1427219820Sjeff case RDMA_CM_EVENT_ADDR_ERROR: 1428219820Sjeff return "RDMA_CM_EVENT_ADDR_ERROR"; 1429219820Sjeff case RDMA_CM_EVENT_ROUTE_RESOLVED: 1430219820Sjeff return "RDMA_CM_EVENT_ROUTE_RESOLVED"; 1431219820Sjeff case RDMA_CM_EVENT_ROUTE_ERROR: 1432219820Sjeff return "RDMA_CM_EVENT_ROUTE_ERROR"; 1433219820Sjeff case RDMA_CM_EVENT_CONNECT_REQUEST: 1434219820Sjeff return "RDMA_CM_EVENT_CONNECT_REQUEST"; 1435219820Sjeff case RDMA_CM_EVENT_CONNECT_RESPONSE: 1436219820Sjeff return "RDMA_CM_EVENT_CONNECT_RESPONSE"; 1437219820Sjeff case RDMA_CM_EVENT_CONNECT_ERROR: 1438219820Sjeff return "RDMA_CM_EVENT_CONNECT_ERROR"; 1439219820Sjeff case RDMA_CM_EVENT_UNREACHABLE: 1440219820Sjeff return "RDMA_CM_EVENT_UNREACHABLE"; 1441219820Sjeff case RDMA_CM_EVENT_REJECTED: 1442219820Sjeff return "RDMA_CM_EVENT_REJECTED"; 1443219820Sjeff case RDMA_CM_EVENT_ESTABLISHED: 1444219820Sjeff return "RDMA_CM_EVENT_ESTABLISHED"; 1445219820Sjeff case RDMA_CM_EVENT_DISCONNECTED: 1446219820Sjeff return "RDMA_CM_EVENT_DISCONNECTED"; 1447219820Sjeff case RDMA_CM_EVENT_DEVICE_REMOVAL: 1448219820Sjeff return "RDMA_CM_EVENT_DEVICE_REMOVAL"; 1449219820Sjeff case RDMA_CM_EVENT_MULTICAST_JOIN: 1450219820Sjeff return "RDMA_CM_EVENT_MULTICAST_JOIN"; 1451219820Sjeff case RDMA_CM_EVENT_MULTICAST_ERROR: 1452219820Sjeff return "RDMA_CM_EVENT_MULTICAST_ERROR"; 1453219820Sjeff case RDMA_CM_EVENT_ADDR_CHANGE: 1454219820Sjeff return "RDMA_CM_EVENT_ADDR_CHANGE"; 1455219820Sjeff case RDMA_CM_EVENT_TIMEWAIT_EXIT: 1456219820Sjeff return "RDMA_CM_EVENT_TIMEWAIT_EXIT"; 1457219820Sjeff default: 1458219820Sjeff return "UNKNOWN EVENT"; 1459219820Sjeff } 1460219820Sjeff} 1461219820Sjeff 1462219820Sjeffint rdma_set_option(struct rdma_cm_id *id, int level, int optname, 1463219820Sjeff void *optval, size_t optlen) 1464219820Sjeff{ 1465219820Sjeff struct ucma_abi_set_option *cmd; 1466219820Sjeff struct cma_id_private *id_priv; 1467219820Sjeff void *msg; 1468219820Sjeff int ret, size; 1469219820Sjeff 1470219820Sjeff CMA_CREATE_MSG_CMD(msg, cmd, UCMA_CMD_SET_OPTION, size); 1471219820Sjeff id_priv = container_of(id, struct cma_id_private, id); 1472219820Sjeff cmd->id = id_priv->handle; 1473219820Sjeff cmd->optval = (uintptr_t) optval; 1474219820Sjeff cmd->level = level; 1475219820Sjeff cmd->optname = optname; 1476219820Sjeff cmd->optlen = optlen; 1477219820Sjeff 1478219820Sjeff ret = write(id->channel->fd, msg, size); 1479219820Sjeff if (ret != size) 1480219820Sjeff return (ret >= 0) ? ERR(ECONNREFUSED) : -1; 1481219820Sjeff 1482219820Sjeff return 0; 1483219820Sjeff} 1484219820Sjeff 1485219820Sjeffint rdma_migrate_id(struct rdma_cm_id *id, struct rdma_event_channel *channel) 1486219820Sjeff{ 1487219820Sjeff struct ucma_abi_migrate_resp *resp; 1488219820Sjeff struct ucma_abi_migrate_id *cmd; 1489219820Sjeff struct cma_id_private *id_priv; 1490219820Sjeff void *msg; 1491219820Sjeff int ret, size; 1492219820Sjeff 1493219820Sjeff id_priv = container_of(id, struct cma_id_private, id); 1494219820Sjeff CMA_CREATE_MSG_CMD_RESP(msg, cmd, resp, UCMA_CMD_MIGRATE_ID, size); 1495219820Sjeff cmd->id = id_priv->handle; 1496219820Sjeff cmd->fd = id->channel->fd; 1497219820Sjeff 1498219820Sjeff ret = write(channel->fd, msg, size); 1499219820Sjeff if (ret != size) 1500219820Sjeff return (ret >= 0) ? ERR(ECONNREFUSED) : -1; 1501219820Sjeff 1502219820Sjeff VALGRIND_MAKE_MEM_DEFINED(resp, sizeof *resp); 1503219820Sjeff 1504219820Sjeff /* 1505219820Sjeff * Eventually if we want to support migrating channels while events are 1506219820Sjeff * being processed on the current channel, we need to block here while 1507219820Sjeff * there are any outstanding events on the current channel for this id 1508219820Sjeff * to prevent the user from processing events for this id on the old 1509219820Sjeff * channel after this call returns. 1510219820Sjeff */ 1511219820Sjeff pthread_mutex_lock(&id_priv->mut); 1512219820Sjeff id->channel = channel; 1513219820Sjeff while (id_priv->events_completed < resp->events_reported) 1514219820Sjeff pthread_cond_wait(&id_priv->cond, &id_priv->mut); 1515219820Sjeff pthread_mutex_unlock(&id_priv->mut); 1516219820Sjeff 1517219820Sjeff return 0; 1518219820Sjeff} 1519