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