Auto-update from upstream
[linux-2.6] / drivers / infiniband / core / ucm.c
1 /*
2  * Copyright (c) 2005 Topspin Communications.  All rights reserved.
3  * Copyright (c) 2005 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: ucm.c 2594 2005-06-13 19:46:02Z libor $
34  */
35 #include <linux/init.h>
36 #include <linux/fs.h>
37 #include <linux/module.h>
38 #include <linux/device.h>
39 #include <linux/err.h>
40 #include <linux/poll.h>
41 #include <linux/file.h>
42 #include <linux/mount.h>
43 #include <linux/cdev.h>
44
45 #include <asm/uaccess.h>
46
47 #include "ucm.h"
48
49 MODULE_AUTHOR("Libor Michalek");
50 MODULE_DESCRIPTION("InfiniBand userspace Connection Manager access");
51 MODULE_LICENSE("Dual BSD/GPL");
52
53 static int ucm_debug_level;
54
55 module_param_named(debug_level, ucm_debug_level, int, 0644);
56 MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0");
57
58 enum {
59         IB_UCM_MAJOR = 231,
60         IB_UCM_MINOR = 255
61 };
62
63 #define IB_UCM_DEV MKDEV(IB_UCM_MAJOR, IB_UCM_MINOR)
64
65 #define PFX "UCM: "
66
67 #define ucm_dbg(format, arg...)                 \
68         do {                                    \
69                 if (ucm_debug_level > 0)        \
70                         printk(KERN_DEBUG PFX format, ## arg); \
71         } while (0)
72
73 static struct semaphore ctx_id_mutex;
74 static struct idr       ctx_id_table;
75 static int              ctx_id_rover = 0;
76
77 static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id)
78 {
79         struct ib_ucm_context *ctx;
80
81         down(&ctx_id_mutex);
82         ctx = idr_find(&ctx_id_table, id);
83         if (!ctx)
84                 ctx = ERR_PTR(-ENOENT);
85         else if (ctx->file != file)
86                 ctx = ERR_PTR(-EINVAL);
87         else
88                 atomic_inc(&ctx->ref);
89         up(&ctx_id_mutex);
90
91         return ctx;
92 }
93
94 static void ib_ucm_ctx_put(struct ib_ucm_context *ctx)
95 {
96         if (atomic_dec_and_test(&ctx->ref))
97                 wake_up(&ctx->wait);
98 }
99
100 static ssize_t ib_ucm_destroy_ctx(struct ib_ucm_file *file, int id)
101 {
102         struct ib_ucm_context *ctx;
103         struct ib_ucm_event *uevent;
104
105         down(&ctx_id_mutex);
106         ctx = idr_find(&ctx_id_table, id);
107         if (!ctx)
108                 ctx = ERR_PTR(-ENOENT);
109         else if (ctx->file != file)
110                 ctx = ERR_PTR(-EINVAL);
111         else
112                 idr_remove(&ctx_id_table, ctx->id);
113         up(&ctx_id_mutex);
114
115         if (IS_ERR(ctx))
116                 return PTR_ERR(ctx);
117
118         atomic_dec(&ctx->ref);
119         wait_event(ctx->wait, !atomic_read(&ctx->ref));
120
121         /* No new events will be generated after destroying the cm_id. */
122         if (!IS_ERR(ctx->cm_id))
123                 ib_destroy_cm_id(ctx->cm_id);
124
125         /* Cleanup events not yet reported to the user. */
126         down(&file->mutex);
127         list_del(&ctx->file_list);
128         while (!list_empty(&ctx->events)) {
129
130                 uevent = list_entry(ctx->events.next,
131                                     struct ib_ucm_event, ctx_list);
132                 list_del(&uevent->file_list);
133                 list_del(&uevent->ctx_list);
134
135                 /* clear incoming connections. */
136                 if (uevent->cm_id)
137                         ib_destroy_cm_id(uevent->cm_id);
138
139                 kfree(uevent);
140         }
141         up(&file->mutex);
142
143         kfree(ctx);
144         return 0;
145 }
146
147 static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
148 {
149         struct ib_ucm_context *ctx;
150         int result;
151
152         ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
153         if (!ctx)
154                 return NULL;
155
156         atomic_set(&ctx->ref, 1);
157         init_waitqueue_head(&ctx->wait);
158         ctx->file = file;
159
160         INIT_LIST_HEAD(&ctx->events);
161
162         list_add_tail(&ctx->file_list, &file->ctxs);
163
164         ctx_id_rover = (ctx_id_rover + 1) & INT_MAX;
165 retry:
166         result = idr_pre_get(&ctx_id_table, GFP_KERNEL);
167         if (!result)
168                 goto error;
169
170         down(&ctx_id_mutex);
171         result = idr_get_new_above(&ctx_id_table, ctx, ctx_id_rover, &ctx->id);
172         up(&ctx_id_mutex);
173
174         if (result == -EAGAIN)
175                 goto retry;
176         if (result)
177                 goto error;
178
179         ucm_dbg("Allocated CM ID <%d>\n", ctx->id);
180
181         return ctx;
182 error:
183         list_del(&ctx->file_list);
184         kfree(ctx);
185
186         return NULL;
187 }
188 /*
189  * Event portion of the API, handle CM events
190  * and allow event polling.
191  */
192 static void ib_ucm_event_path_get(struct ib_ucm_path_rec *upath,
193                                   struct ib_sa_path_rec  *kpath)
194 {
195         if (!kpath || !upath)
196                 return;
197
198         memcpy(upath->dgid, kpath->dgid.raw, sizeof *upath->dgid);
199         memcpy(upath->sgid, kpath->sgid.raw, sizeof *upath->sgid);
200
201         upath->dlid             = kpath->dlid;
202         upath->slid             = kpath->slid;
203         upath->raw_traffic      = kpath->raw_traffic;
204         upath->flow_label       = kpath->flow_label;
205         upath->hop_limit        = kpath->hop_limit;
206         upath->traffic_class    = kpath->traffic_class;
207         upath->reversible       = kpath->reversible;
208         upath->numb_path        = kpath->numb_path;
209         upath->pkey             = kpath->pkey;
210         upath->sl               = kpath->sl;
211         upath->mtu_selector     = kpath->mtu_selector;
212         upath->mtu              = kpath->mtu;
213         upath->rate_selector    = kpath->rate_selector;
214         upath->rate             = kpath->rate;
215         upath->packet_life_time = kpath->packet_life_time;
216         upath->preference       = kpath->preference;
217
218         upath->packet_life_time_selector =
219                 kpath->packet_life_time_selector;
220 }
221
222 static void ib_ucm_event_req_get(struct ib_ucm_context *ctx,
223                                  struct ib_ucm_req_event_resp *ureq,
224                                  struct ib_cm_req_event_param *kreq)
225 {
226         ureq->listen_id = ctx->id;
227
228         ureq->remote_ca_guid             = kreq->remote_ca_guid;
229         ureq->remote_qkey                = kreq->remote_qkey;
230         ureq->remote_qpn                 = kreq->remote_qpn;
231         ureq->qp_type                    = kreq->qp_type;
232         ureq->starting_psn               = kreq->starting_psn;
233         ureq->responder_resources        = kreq->responder_resources;
234         ureq->initiator_depth            = kreq->initiator_depth;
235         ureq->local_cm_response_timeout  = kreq->local_cm_response_timeout;
236         ureq->flow_control               = kreq->flow_control;
237         ureq->remote_cm_response_timeout = kreq->remote_cm_response_timeout;
238         ureq->retry_count                = kreq->retry_count;
239         ureq->rnr_retry_count            = kreq->rnr_retry_count;
240         ureq->srq                        = kreq->srq;
241
242         ib_ucm_event_path_get(&ureq->primary_path, kreq->primary_path);
243         ib_ucm_event_path_get(&ureq->alternate_path, kreq->alternate_path);
244 }
245
246 static void ib_ucm_event_rep_get(struct ib_ucm_rep_event_resp *urep,
247                                  struct ib_cm_rep_event_param *krep)
248 {
249         urep->remote_ca_guid      = krep->remote_ca_guid;
250         urep->remote_qkey         = krep->remote_qkey;
251         urep->remote_qpn          = krep->remote_qpn;
252         urep->starting_psn        = krep->starting_psn;
253         urep->responder_resources = krep->responder_resources;
254         urep->initiator_depth     = krep->initiator_depth;
255         urep->target_ack_delay    = krep->target_ack_delay;
256         urep->failover_accepted   = krep->failover_accepted;
257         urep->flow_control        = krep->flow_control;
258         urep->rnr_retry_count     = krep->rnr_retry_count;
259         urep->srq                 = krep->srq;
260 }
261
262 static void ib_ucm_event_sidr_req_get(struct ib_ucm_context *ctx,
263                                       struct ib_ucm_sidr_req_event_resp *ureq,
264                                       struct ib_cm_sidr_req_event_param *kreq)
265 {
266         ureq->listen_id = ctx->id;
267         ureq->pkey      = kreq->pkey;
268 }
269
270 static void ib_ucm_event_sidr_rep_get(struct ib_ucm_sidr_rep_event_resp *urep,
271                                       struct ib_cm_sidr_rep_event_param *krep)
272 {
273         urep->status = krep->status;
274         urep->qkey   = krep->qkey;
275         urep->qpn    = krep->qpn;
276 };
277
278 static int ib_ucm_event_process(struct ib_ucm_context *ctx,
279                                 struct ib_cm_event *evt,
280                                 struct ib_ucm_event *uvt)
281 {
282         void *info = NULL;
283
284         switch (evt->event) {
285         case IB_CM_REQ_RECEIVED:
286                 ib_ucm_event_req_get(ctx, &uvt->resp.u.req_resp,
287                                      &evt->param.req_rcvd);
288                 uvt->data_len      = IB_CM_REQ_PRIVATE_DATA_SIZE;
289                 uvt->resp.present  = IB_UCM_PRES_PRIMARY;
290                 uvt->resp.present |= (evt->param.req_rcvd.alternate_path ?
291                                       IB_UCM_PRES_ALTERNATE : 0);
292                 break;
293         case IB_CM_REP_RECEIVED:
294                 ib_ucm_event_rep_get(&uvt->resp.u.rep_resp,
295                                      &evt->param.rep_rcvd);
296                 uvt->data_len = IB_CM_REP_PRIVATE_DATA_SIZE;
297                 break;
298         case IB_CM_RTU_RECEIVED:
299                 uvt->data_len = IB_CM_RTU_PRIVATE_DATA_SIZE;
300                 uvt->resp.u.send_status = evt->param.send_status;
301                 break;
302         case IB_CM_DREQ_RECEIVED:
303                 uvt->data_len = IB_CM_DREQ_PRIVATE_DATA_SIZE;
304                 uvt->resp.u.send_status = evt->param.send_status;
305                 break;
306         case IB_CM_DREP_RECEIVED:
307                 uvt->data_len = IB_CM_DREP_PRIVATE_DATA_SIZE;
308                 uvt->resp.u.send_status = evt->param.send_status;
309                 break;
310         case IB_CM_MRA_RECEIVED:
311                 uvt->resp.u.mra_resp.timeout =
312                                         evt->param.mra_rcvd.service_timeout;
313                 uvt->data_len = IB_CM_MRA_PRIVATE_DATA_SIZE;
314                 break;
315         case IB_CM_REJ_RECEIVED:
316                 uvt->resp.u.rej_resp.reason = evt->param.rej_rcvd.reason;
317                 uvt->data_len = IB_CM_REJ_PRIVATE_DATA_SIZE;
318                 uvt->info_len = evt->param.rej_rcvd.ari_length;
319                 info          = evt->param.rej_rcvd.ari;
320                 break;
321         case IB_CM_LAP_RECEIVED:
322                 ib_ucm_event_path_get(&uvt->resp.u.lap_resp.path,
323                                       evt->param.lap_rcvd.alternate_path);
324                 uvt->data_len = IB_CM_LAP_PRIVATE_DATA_SIZE;
325                 uvt->resp.present = IB_UCM_PRES_ALTERNATE;
326                 break;
327         case IB_CM_APR_RECEIVED:
328                 uvt->resp.u.apr_resp.status = evt->param.apr_rcvd.ap_status;
329                 uvt->data_len = IB_CM_APR_PRIVATE_DATA_SIZE;
330                 uvt->info_len = evt->param.apr_rcvd.info_len;
331                 info          = evt->param.apr_rcvd.apr_info;
332                 break;
333         case IB_CM_SIDR_REQ_RECEIVED:
334                 ib_ucm_event_sidr_req_get(ctx, &uvt->resp.u.sidr_req_resp,
335                                           &evt->param.sidr_req_rcvd);
336                 uvt->data_len = IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE;
337                 break;
338         case IB_CM_SIDR_REP_RECEIVED:
339                 ib_ucm_event_sidr_rep_get(&uvt->resp.u.sidr_rep_resp,
340                                           &evt->param.sidr_rep_rcvd);
341                 uvt->data_len = IB_CM_SIDR_REP_PRIVATE_DATA_SIZE;
342                 uvt->info_len = evt->param.sidr_rep_rcvd.info_len;
343                 info          = evt->param.sidr_rep_rcvd.info;
344                 break;
345         default:
346                 uvt->resp.u.send_status = evt->param.send_status;
347                 break;
348         }
349
350         if (uvt->data_len) {
351                 uvt->data = kmalloc(uvt->data_len, GFP_KERNEL);
352                 if (!uvt->data)
353                         goto err1;
354
355                 memcpy(uvt->data, evt->private_data, uvt->data_len);
356                 uvt->resp.present |= IB_UCM_PRES_DATA;
357         }
358
359         if (uvt->info_len) {
360                 uvt->info = kmalloc(uvt->info_len, GFP_KERNEL);
361                 if (!uvt->info)
362                         goto err2;
363
364                 memcpy(uvt->info, info, uvt->info_len);
365                 uvt->resp.present |= IB_UCM_PRES_INFO;
366         }
367         return 0;
368
369 err2:
370         kfree(uvt->data);
371 err1:
372         return -ENOMEM;
373 }
374
375 static int ib_ucm_event_handler(struct ib_cm_id *cm_id,
376                                 struct ib_cm_event *event)
377 {
378         struct ib_ucm_event *uevent;
379         struct ib_ucm_context *ctx;
380         int result = 0;
381         int id;
382
383         ctx = cm_id->context;
384
385         if (event->event == IB_CM_REQ_RECEIVED ||
386             event->event == IB_CM_SIDR_REQ_RECEIVED)
387                 id = IB_UCM_CM_ID_INVALID;
388         else
389                 id = ctx->id;
390
391         uevent = kmalloc(sizeof(*uevent), GFP_KERNEL);
392         if (!uevent)
393                 goto err1;
394
395         memset(uevent, 0, sizeof(*uevent));
396         uevent->resp.id    = id;
397         uevent->resp.event = event->event;
398
399         result = ib_ucm_event_process(ctx, event, uevent);
400         if (result)
401                 goto err2;
402
403         uevent->ctx   = ctx;
404         uevent->cm_id = (id == IB_UCM_CM_ID_INVALID) ? cm_id : NULL;
405
406         down(&ctx->file->mutex);
407         list_add_tail(&uevent->file_list, &ctx->file->events);
408         list_add_tail(&uevent->ctx_list, &ctx->events);
409         wake_up_interruptible(&ctx->file->poll_wait);
410         up(&ctx->file->mutex);
411         return 0;
412
413 err2:
414         kfree(uevent);
415 err1:
416         /* Destroy new cm_id's */
417         return (id == IB_UCM_CM_ID_INVALID);
418 }
419
420 static ssize_t ib_ucm_event(struct ib_ucm_file *file,
421                             const char __user *inbuf,
422                             int in_len, int out_len)
423 {
424         struct ib_ucm_context *ctx;
425         struct ib_ucm_event_get cmd;
426         struct ib_ucm_event *uevent = NULL;
427         int result = 0;
428         DEFINE_WAIT(wait);
429
430         if (out_len < sizeof(struct ib_ucm_event_resp))
431                 return -ENOSPC;
432
433         if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
434                 return -EFAULT;
435         /*
436          * wait
437          */
438         down(&file->mutex);
439
440         while (list_empty(&file->events)) {
441
442                 if (file->filp->f_flags & O_NONBLOCK) {
443                         result = -EAGAIN;
444                         break;
445                 }
446
447                 if (signal_pending(current)) {
448                         result = -ERESTARTSYS;
449                         break;
450                 }
451
452                 prepare_to_wait(&file->poll_wait, &wait, TASK_INTERRUPTIBLE);
453
454                 up(&file->mutex);
455                 schedule();
456                 down(&file->mutex);
457
458                 finish_wait(&file->poll_wait, &wait);
459         }
460
461         if (result)
462                 goto done;
463
464         uevent = list_entry(file->events.next, struct ib_ucm_event, file_list);
465
466         if (!uevent->cm_id)
467                 goto user;
468
469         ctx = ib_ucm_ctx_alloc(file);
470         if (!ctx) {
471                 result = -ENOMEM;
472                 goto done;
473         }
474
475         ctx->cm_id          = uevent->cm_id;
476         ctx->cm_id->context = ctx;
477
478         uevent->resp.id = ctx->id;
479
480 user:
481         if (copy_to_user((void __user *)(unsigned long)cmd.response,
482                          &uevent->resp, sizeof(uevent->resp))) {
483                 result = -EFAULT;
484                 goto done;
485         }
486
487         if (uevent->data) {
488
489                 if (cmd.data_len < uevent->data_len) {
490                         result = -ENOMEM;
491                         goto done;
492                 }
493
494                 if (copy_to_user((void __user *)(unsigned long)cmd.data,
495                                  uevent->data, uevent->data_len)) {
496                         result = -EFAULT;
497                         goto done;
498                 }
499         }
500
501         if (uevent->info) {
502
503                 if (cmd.info_len < uevent->info_len) {
504                         result = -ENOMEM;
505                         goto done;
506                 }
507
508                 if (copy_to_user((void __user *)(unsigned long)cmd.info,
509                                  uevent->info, uevent->info_len)) {
510                         result = -EFAULT;
511                         goto done;
512                 }
513         }
514
515         list_del(&uevent->file_list);
516         list_del(&uevent->ctx_list);
517
518         kfree(uevent->data);
519         kfree(uevent->info);
520         kfree(uevent);
521 done:
522         up(&file->mutex);
523         return result;
524 }
525
526
527 static ssize_t ib_ucm_create_id(struct ib_ucm_file *file,
528                                 const char __user *inbuf,
529                                 int in_len, int out_len)
530 {
531         struct ib_ucm_create_id cmd;
532         struct ib_ucm_create_id_resp resp;
533         struct ib_ucm_context *ctx;
534         int result;
535
536         if (out_len < sizeof(resp))
537                 return -ENOSPC;
538
539         if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
540                 return -EFAULT;
541
542         down(&file->mutex);
543         ctx = ib_ucm_ctx_alloc(file);
544         up(&file->mutex);
545         if (!ctx)
546                 return -ENOMEM;
547
548         ctx->cm_id = ib_create_cm_id(ib_ucm_event_handler, ctx);
549         if (IS_ERR(ctx->cm_id)) {
550                 result = PTR_ERR(ctx->cm_id);
551                 goto err;
552         }
553
554         resp.id = ctx->id;
555         if (copy_to_user((void __user *)(unsigned long)cmd.response,
556                          &resp, sizeof(resp))) {
557                 result = -EFAULT;
558                 goto err;
559         }
560
561         return 0;
562
563 err:
564         ib_ucm_destroy_ctx(file, ctx->id);
565         return result;
566 }
567
568 static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file,
569                                  const char __user *inbuf,
570                                  int in_len, int out_len)
571 {
572         struct ib_ucm_destroy_id cmd;
573
574         if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
575                 return -EFAULT;
576
577         return ib_ucm_destroy_ctx(file, cmd.id);
578 }
579
580 static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file,
581                               const char __user *inbuf,
582                               int in_len, int out_len)
583 {
584         struct ib_ucm_attr_id_resp resp;
585         struct ib_ucm_attr_id cmd;
586         struct ib_ucm_context *ctx;
587         int result = 0;
588
589         if (out_len < sizeof(resp))
590                 return -ENOSPC;
591
592         if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
593                 return -EFAULT;
594
595         ctx = ib_ucm_ctx_get(file, cmd.id);
596         if (IS_ERR(ctx))
597                 return PTR_ERR(ctx);
598
599         resp.service_id   = ctx->cm_id->service_id;
600         resp.service_mask = ctx->cm_id->service_mask;
601         resp.local_id     = ctx->cm_id->local_id;
602         resp.remote_id    = ctx->cm_id->remote_id;
603
604         if (copy_to_user((void __user *)(unsigned long)cmd.response,
605                          &resp, sizeof(resp)))
606                 result = -EFAULT;
607
608         ib_ucm_ctx_put(ctx);
609         return result;
610 }
611
612 static ssize_t ib_ucm_listen(struct ib_ucm_file *file,
613                              const char __user *inbuf,
614                              int in_len, int out_len)
615 {
616         struct ib_ucm_listen cmd;
617         struct ib_ucm_context *ctx;
618         int result;
619
620         if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
621                 return -EFAULT;
622
623         ctx = ib_ucm_ctx_get(file, cmd.id);
624         if (IS_ERR(ctx))
625                 return PTR_ERR(ctx);
626
627         result = ib_cm_listen(ctx->cm_id, cmd.service_id, cmd.service_mask);
628         ib_ucm_ctx_put(ctx);
629         return result;
630 }
631
632 static ssize_t ib_ucm_establish(struct ib_ucm_file *file,
633                                 const char __user *inbuf,
634                                 int in_len, int out_len)
635 {
636         struct ib_ucm_establish cmd;
637         struct ib_ucm_context *ctx;
638         int result;
639
640         if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
641                 return -EFAULT;
642
643         ctx = ib_ucm_ctx_get(file, cmd.id);
644         if (IS_ERR(ctx))
645                 return PTR_ERR(ctx);
646
647         result = ib_cm_establish(ctx->cm_id);
648         ib_ucm_ctx_put(ctx);
649         return result;
650 }
651
652 static int ib_ucm_alloc_data(const void **dest, u64 src, u32 len)
653 {
654         void *data;
655
656         *dest = NULL;
657
658         if (!len)
659                 return 0;
660
661         data = kmalloc(len, GFP_KERNEL);
662         if (!data)
663                 return -ENOMEM;
664
665         if (copy_from_user(data, (void __user *)(unsigned long)src, len)) {
666                 kfree(data);
667                 return -EFAULT;
668         }
669
670         *dest = data;
671         return 0;
672 }
673
674 static int ib_ucm_path_get(struct ib_sa_path_rec **path, u64 src)
675 {
676         struct ib_ucm_path_rec ucm_path;
677         struct ib_sa_path_rec  *sa_path;
678
679         *path = NULL;
680
681         if (!src)
682                 return 0;
683
684         sa_path = kmalloc(sizeof(*sa_path), GFP_KERNEL);
685         if (!sa_path)
686                 return -ENOMEM;
687
688         if (copy_from_user(&ucm_path, (void __user *)(unsigned long)src,
689                            sizeof(ucm_path))) {
690
691                 kfree(sa_path);
692                 return -EFAULT;
693         }
694
695         memcpy(sa_path->dgid.raw, ucm_path.dgid, sizeof sa_path->dgid);
696         memcpy(sa_path->sgid.raw, ucm_path.sgid, sizeof sa_path->sgid);
697
698         sa_path->dlid             = ucm_path.dlid;
699         sa_path->slid             = ucm_path.slid;
700         sa_path->raw_traffic      = ucm_path.raw_traffic;
701         sa_path->flow_label       = ucm_path.flow_label;
702         sa_path->hop_limit        = ucm_path.hop_limit;
703         sa_path->traffic_class    = ucm_path.traffic_class;
704         sa_path->reversible       = ucm_path.reversible;
705         sa_path->numb_path        = ucm_path.numb_path;
706         sa_path->pkey             = ucm_path.pkey;
707         sa_path->sl               = ucm_path.sl;
708         sa_path->mtu_selector     = ucm_path.mtu_selector;
709         sa_path->mtu              = ucm_path.mtu;
710         sa_path->rate_selector    = ucm_path.rate_selector;
711         sa_path->rate             = ucm_path.rate;
712         sa_path->packet_life_time = ucm_path.packet_life_time;
713         sa_path->preference       = ucm_path.preference;
714
715         sa_path->packet_life_time_selector =
716                 ucm_path.packet_life_time_selector;
717
718         *path = sa_path;
719         return 0;
720 }
721
722 static ssize_t ib_ucm_send_req(struct ib_ucm_file *file,
723                                const char __user *inbuf,
724                                int in_len, int out_len)
725 {
726         struct ib_cm_req_param param;
727         struct ib_ucm_context *ctx;
728         struct ib_ucm_req cmd;
729         int result;
730
731         param.private_data   = NULL;
732         param.primary_path   = NULL;
733         param.alternate_path = NULL;
734
735         if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
736                 return -EFAULT;
737
738         result = ib_ucm_alloc_data(&param.private_data, cmd.data, cmd.len);
739         if (result)
740                 goto done;
741
742         result = ib_ucm_path_get(&param.primary_path, cmd.primary_path);
743         if (result)
744                 goto done;
745
746         result = ib_ucm_path_get(&param.alternate_path, cmd.alternate_path);
747         if (result)
748                 goto done;
749
750         param.private_data_len           = cmd.len;
751         param.service_id                 = cmd.sid;
752         param.qp_num                     = cmd.qpn;
753         param.qp_type                    = cmd.qp_type;
754         param.starting_psn               = cmd.psn;
755         param.peer_to_peer               = cmd.peer_to_peer;
756         param.responder_resources        = cmd.responder_resources;
757         param.initiator_depth            = cmd.initiator_depth;
758         param.remote_cm_response_timeout = cmd.remote_cm_response_timeout;
759         param.flow_control               = cmd.flow_control;
760         param.local_cm_response_timeout  = cmd.local_cm_response_timeout;
761         param.retry_count                = cmd.retry_count;
762         param.rnr_retry_count            = cmd.rnr_retry_count;
763         param.max_cm_retries             = cmd.max_cm_retries;
764         param.srq                        = cmd.srq;
765
766         ctx = ib_ucm_ctx_get(file, cmd.id);
767         if (!IS_ERR(ctx)) {
768                 result = ib_send_cm_req(ctx->cm_id, &param);
769                 ib_ucm_ctx_put(ctx);
770         } else
771                 result = PTR_ERR(ctx);
772
773 done:
774         kfree(param.private_data);
775         kfree(param.primary_path);
776         kfree(param.alternate_path);
777         return result;
778 }
779
780 static ssize_t ib_ucm_send_rep(struct ib_ucm_file *file,
781                                const char __user *inbuf,
782                                int in_len, int out_len)
783 {
784         struct ib_cm_rep_param param;
785         struct ib_ucm_context *ctx;
786         struct ib_ucm_rep cmd;
787         int result;
788
789         param.private_data = NULL;
790
791         if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
792                 return -EFAULT;
793
794         result = ib_ucm_alloc_data(&param.private_data, cmd.data, cmd.len);
795         if (result)
796                 return result;
797
798         param.qp_num              = cmd.qpn;
799         param.starting_psn        = cmd.psn;
800         param.private_data_len    = cmd.len;
801         param.responder_resources = cmd.responder_resources;
802         param.initiator_depth     = cmd.initiator_depth;
803         param.target_ack_delay    = cmd.target_ack_delay;
804         param.failover_accepted   = cmd.failover_accepted;
805         param.flow_control        = cmd.flow_control;
806         param.rnr_retry_count     = cmd.rnr_retry_count;
807         param.srq                 = cmd.srq;
808
809         ctx = ib_ucm_ctx_get(file, cmd.id);
810         if (!IS_ERR(ctx)) {
811                 result = ib_send_cm_rep(ctx->cm_id, &param);
812                 ib_ucm_ctx_put(ctx);
813         } else
814                 result = PTR_ERR(ctx);
815
816         kfree(param.private_data);
817         return result;
818 }
819
820 static ssize_t ib_ucm_send_private_data(struct ib_ucm_file *file,
821                                         const char __user *inbuf, int in_len,
822                                         int (*func)(struct ib_cm_id *cm_id,
823                                                     const void *private_data,
824                                                     u8 private_data_len))
825 {
826         struct ib_ucm_private_data cmd;
827         struct ib_ucm_context *ctx;
828         const void *private_data = NULL;
829         int result;
830
831         if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
832                 return -EFAULT;
833
834         result = ib_ucm_alloc_data(&private_data, cmd.data, cmd.len);
835         if (result)
836                 return result;
837
838         ctx = ib_ucm_ctx_get(file, cmd.id);
839         if (!IS_ERR(ctx)) {
840                 result = func(ctx->cm_id, private_data, cmd.len);
841                 ib_ucm_ctx_put(ctx);
842         } else
843                 result = PTR_ERR(ctx);
844
845         kfree(private_data);
846         return result;
847 }
848
849 static ssize_t ib_ucm_send_rtu(struct ib_ucm_file *file,
850                                const char __user *inbuf,
851                                int in_len, int out_len)
852 {
853         return ib_ucm_send_private_data(file, inbuf, in_len, ib_send_cm_rtu);
854 }
855
856 static ssize_t ib_ucm_send_dreq(struct ib_ucm_file *file,
857                                 const char __user *inbuf,
858                                 int in_len, int out_len)
859 {
860         return ib_ucm_send_private_data(file, inbuf, in_len, ib_send_cm_dreq);
861 }
862
863 static ssize_t ib_ucm_send_drep(struct ib_ucm_file *file,
864                                 const char __user *inbuf,
865                                 int in_len, int out_len)
866 {
867         return ib_ucm_send_private_data(file, inbuf, in_len, ib_send_cm_drep);
868 }
869
870 static ssize_t ib_ucm_send_info(struct ib_ucm_file *file,
871                                 const char __user *inbuf, int in_len,
872                                 int (*func)(struct ib_cm_id *cm_id,
873                                             int status,
874                                             const void *info,
875                                             u8 info_len,
876                                             const void *data,
877                                             u8 data_len))
878 {
879         struct ib_ucm_context *ctx;
880         struct ib_ucm_info cmd;
881         const void *data = NULL;
882         const void *info = NULL;
883         int result;
884
885         if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
886                 return -EFAULT;
887
888         result = ib_ucm_alloc_data(&data, cmd.data, cmd.data_len);
889         if (result)
890                 goto done;
891
892         result = ib_ucm_alloc_data(&info, cmd.info, cmd.info_len);
893         if (result)
894                 goto done;
895
896         ctx = ib_ucm_ctx_get(file, cmd.id);
897         if (!IS_ERR(ctx)) {
898                 result = func(ctx->cm_id, cmd.status, info, cmd.info_len,
899                               data, cmd.data_len);
900                 ib_ucm_ctx_put(ctx);
901         } else
902                 result = PTR_ERR(ctx);
903
904 done:
905         kfree(data);
906         kfree(info);
907         return result;
908 }
909
910 static ssize_t ib_ucm_send_rej(struct ib_ucm_file *file,
911                                const char __user *inbuf,
912                                int in_len, int out_len)
913 {
914         return ib_ucm_send_info(file, inbuf, in_len, (void *)ib_send_cm_rej);
915 }
916
917 static ssize_t ib_ucm_send_apr(struct ib_ucm_file *file,
918                                const char __user *inbuf,
919                                int in_len, int out_len)
920 {
921         return ib_ucm_send_info(file, inbuf, in_len, (void *)ib_send_cm_apr);
922 }
923
924 static ssize_t ib_ucm_send_mra(struct ib_ucm_file *file,
925                                const char __user *inbuf,
926                                int in_len, int out_len)
927 {
928         struct ib_ucm_context *ctx;
929         struct ib_ucm_mra cmd;
930         const void *data = NULL;
931         int result;
932
933         if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
934                 return -EFAULT;
935
936         result = ib_ucm_alloc_data(&data, cmd.data, cmd.len);
937         if (result)
938                 return result;
939
940         ctx = ib_ucm_ctx_get(file, cmd.id);
941         if (!IS_ERR(ctx)) {
942                 result = ib_send_cm_mra(ctx->cm_id, cmd.timeout, data, cmd.len);
943                 ib_ucm_ctx_put(ctx);
944         } else
945                 result = PTR_ERR(ctx);
946
947         kfree(data);
948         return result;
949 }
950
951 static ssize_t ib_ucm_send_lap(struct ib_ucm_file *file,
952                                const char __user *inbuf,
953                                int in_len, int out_len)
954 {
955         struct ib_ucm_context *ctx;
956         struct ib_sa_path_rec *path = NULL;
957         struct ib_ucm_lap cmd;
958         const void *data = NULL;
959         int result;
960
961         if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
962                 return -EFAULT;
963
964         result = ib_ucm_alloc_data(&data, cmd.data, cmd.len);
965         if (result)
966                 goto done;
967
968         result = ib_ucm_path_get(&path, cmd.path);
969         if (result)
970                 goto done;
971
972         ctx = ib_ucm_ctx_get(file, cmd.id);
973         if (!IS_ERR(ctx)) {
974                 result = ib_send_cm_lap(ctx->cm_id, path, data, cmd.len);
975                 ib_ucm_ctx_put(ctx);
976         } else
977                 result = PTR_ERR(ctx);
978
979 done:
980         kfree(data);
981         kfree(path);
982         return result;
983 }
984
985 static ssize_t ib_ucm_send_sidr_req(struct ib_ucm_file *file,
986                                     const char __user *inbuf,
987                                     int in_len, int out_len)
988 {
989         struct ib_cm_sidr_req_param param;
990         struct ib_ucm_context *ctx;
991         struct ib_ucm_sidr_req cmd;
992         int result;
993
994         param.private_data = NULL;
995         param.path = NULL;
996
997         if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
998                 return -EFAULT;
999
1000         result = ib_ucm_alloc_data(&param.private_data, cmd.data, cmd.len);
1001         if (result)
1002                 goto done;
1003
1004         result = ib_ucm_path_get(&param.path, cmd.path);
1005         if (result)
1006                 goto done;
1007
1008         param.private_data_len = cmd.len;
1009         param.service_id       = cmd.sid;
1010         param.timeout_ms       = cmd.timeout;
1011         param.max_cm_retries   = cmd.max_cm_retries;
1012         param.pkey             = cmd.pkey;
1013
1014         ctx = ib_ucm_ctx_get(file, cmd.id);
1015         if (!IS_ERR(ctx)) {
1016                 result = ib_send_cm_sidr_req(ctx->cm_id, &param);
1017                 ib_ucm_ctx_put(ctx);
1018         } else
1019                 result = PTR_ERR(ctx);
1020
1021 done:
1022         kfree(param.private_data);
1023         kfree(param.path);
1024         return result;
1025 }
1026
1027 static ssize_t ib_ucm_send_sidr_rep(struct ib_ucm_file *file,
1028                                     const char __user *inbuf,
1029                                     int in_len, int out_len)
1030 {
1031         struct ib_cm_sidr_rep_param param;
1032         struct ib_ucm_sidr_rep cmd;
1033         struct ib_ucm_context *ctx;
1034         int result;
1035
1036         param.info = NULL;
1037
1038         if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
1039                 return -EFAULT;
1040
1041         result = ib_ucm_alloc_data(&param.private_data,
1042                                    cmd.data, cmd.data_len);
1043         if (result)
1044                 goto done;
1045
1046         result = ib_ucm_alloc_data(&param.info, cmd.info, cmd.info_len);
1047         if (result)
1048                 goto done;
1049
1050         param.qp_num            = cmd.qpn;
1051         param.qkey              = cmd.qkey;
1052         param.status            = cmd.status;
1053         param.info_length       = cmd.info_len;
1054         param.private_data_len  = cmd.data_len;
1055
1056         ctx = ib_ucm_ctx_get(file, cmd.id);
1057         if (!IS_ERR(ctx)) {
1058                 result = ib_send_cm_sidr_rep(ctx->cm_id, &param);
1059                 ib_ucm_ctx_put(ctx);
1060         } else
1061                 result = PTR_ERR(ctx);
1062
1063 done:
1064         kfree(param.private_data);
1065         kfree(param.info);
1066         return result;
1067 }
1068
1069 static ssize_t (*ucm_cmd_table[])(struct ib_ucm_file *file,
1070                                   const char __user *inbuf,
1071                                   int in_len, int out_len) = {
1072         [IB_USER_CM_CMD_CREATE_ID]     = ib_ucm_create_id,
1073         [IB_USER_CM_CMD_DESTROY_ID]    = ib_ucm_destroy_id,
1074         [IB_USER_CM_CMD_ATTR_ID]       = ib_ucm_attr_id,
1075         [IB_USER_CM_CMD_LISTEN]        = ib_ucm_listen,
1076         [IB_USER_CM_CMD_ESTABLISH]     = ib_ucm_establish,
1077         [IB_USER_CM_CMD_SEND_REQ]      = ib_ucm_send_req,
1078         [IB_USER_CM_CMD_SEND_REP]      = ib_ucm_send_rep,
1079         [IB_USER_CM_CMD_SEND_RTU]      = ib_ucm_send_rtu,
1080         [IB_USER_CM_CMD_SEND_DREQ]     = ib_ucm_send_dreq,
1081         [IB_USER_CM_CMD_SEND_DREP]     = ib_ucm_send_drep,
1082         [IB_USER_CM_CMD_SEND_REJ]      = ib_ucm_send_rej,
1083         [IB_USER_CM_CMD_SEND_MRA]      = ib_ucm_send_mra,
1084         [IB_USER_CM_CMD_SEND_LAP]      = ib_ucm_send_lap,
1085         [IB_USER_CM_CMD_SEND_APR]      = ib_ucm_send_apr,
1086         [IB_USER_CM_CMD_SEND_SIDR_REQ] = ib_ucm_send_sidr_req,
1087         [IB_USER_CM_CMD_SEND_SIDR_REP] = ib_ucm_send_sidr_rep,
1088         [IB_USER_CM_CMD_EVENT]         = ib_ucm_event,
1089 };
1090
1091 static ssize_t ib_ucm_write(struct file *filp, const char __user *buf,
1092                             size_t len, loff_t *pos)
1093 {
1094         struct ib_ucm_file *file = filp->private_data;
1095         struct ib_ucm_cmd_hdr hdr;
1096         ssize_t result;
1097
1098         if (len < sizeof(hdr))
1099                 return -EINVAL;
1100
1101         if (copy_from_user(&hdr, buf, sizeof(hdr)))
1102                 return -EFAULT;
1103
1104         ucm_dbg("Write. cmd <%d> in <%d> out <%d> len <%Zu>\n",
1105                 hdr.cmd, hdr.in, hdr.out, len);
1106
1107         if (hdr.cmd < 0 || hdr.cmd >= ARRAY_SIZE(ucm_cmd_table))
1108                 return -EINVAL;
1109
1110         if (hdr.in + sizeof(hdr) > len)
1111                 return -EINVAL;
1112
1113         result = ucm_cmd_table[hdr.cmd](file, buf + sizeof(hdr),
1114                                         hdr.in, hdr.out);
1115         if (!result)
1116                 result = len;
1117
1118         return result;
1119 }
1120
1121 static unsigned int ib_ucm_poll(struct file *filp,
1122                                 struct poll_table_struct *wait)
1123 {
1124         struct ib_ucm_file *file = filp->private_data;
1125         unsigned int mask = 0;
1126
1127         poll_wait(filp, &file->poll_wait, wait);
1128
1129         if (!list_empty(&file->events))
1130                 mask = POLLIN | POLLRDNORM;
1131
1132         return mask;
1133 }
1134
1135 static int ib_ucm_open(struct inode *inode, struct file *filp)
1136 {
1137         struct ib_ucm_file *file;
1138
1139         file = kmalloc(sizeof(*file), GFP_KERNEL);
1140         if (!file)
1141                 return -ENOMEM;
1142
1143         INIT_LIST_HEAD(&file->events);
1144         INIT_LIST_HEAD(&file->ctxs);
1145         init_waitqueue_head(&file->poll_wait);
1146
1147         init_MUTEX(&file->mutex);
1148
1149         filp->private_data = file;
1150         file->filp = filp;
1151
1152         ucm_dbg("Created struct\n");
1153
1154         return 0;
1155 }
1156
1157 static int ib_ucm_close(struct inode *inode, struct file *filp)
1158 {
1159         struct ib_ucm_file *file = filp->private_data;
1160         struct ib_ucm_context *ctx;
1161
1162         down(&file->mutex);
1163         while (!list_empty(&file->ctxs)) {
1164
1165                 ctx = list_entry(file->ctxs.next,
1166                                  struct ib_ucm_context, file_list);
1167
1168                 up(&file->mutex);
1169                 ib_ucm_destroy_ctx(file, ctx->id);
1170                 down(&file->mutex);
1171         }
1172         up(&file->mutex);
1173         kfree(file);
1174         return 0;
1175 }
1176
1177 static struct file_operations ib_ucm_fops = {
1178         .owner   = THIS_MODULE,
1179         .open    = ib_ucm_open,
1180         .release = ib_ucm_close,
1181         .write   = ib_ucm_write,
1182         .poll    = ib_ucm_poll,
1183 };
1184
1185
1186 static struct class *ib_ucm_class;
1187 static struct cdev        ib_ucm_cdev;
1188
1189 static int __init ib_ucm_init(void)
1190 {
1191         int result;
1192
1193         result = register_chrdev_region(IB_UCM_DEV, 1, "infiniband_cm");
1194         if (result) {
1195                 ucm_dbg("Error <%d> registering dev\n", result);
1196                 goto err_chr;
1197         }
1198
1199         cdev_init(&ib_ucm_cdev, &ib_ucm_fops);
1200
1201         result = cdev_add(&ib_ucm_cdev, IB_UCM_DEV, 1);
1202         if (result) {
1203                 ucm_dbg("Error <%d> adding cdev\n", result);
1204                 goto err_cdev;
1205         }
1206
1207         ib_ucm_class = class_create(THIS_MODULE, "infiniband_cm");
1208         if (IS_ERR(ib_ucm_class)) {
1209                 result = PTR_ERR(ib_ucm_class);
1210                 ucm_dbg("Error <%d> creating class\n", result);
1211                 goto err_class;
1212         }
1213
1214         class_device_create(ib_ucm_class, IB_UCM_DEV, NULL, "ucm");
1215
1216         idr_init(&ctx_id_table);
1217         init_MUTEX(&ctx_id_mutex);
1218
1219         return 0;
1220 err_class:
1221         cdev_del(&ib_ucm_cdev);
1222 err_cdev:
1223         unregister_chrdev_region(IB_UCM_DEV, 1);
1224 err_chr:
1225         return result;
1226 }
1227
1228 static void __exit ib_ucm_cleanup(void)
1229 {
1230         class_device_destroy(ib_ucm_class, IB_UCM_DEV);
1231         class_destroy(ib_ucm_class);
1232         cdev_del(&ib_ucm_cdev);
1233         unregister_chrdev_region(IB_UCM_DEV, 1);
1234 }
1235
1236 module_init(ib_ucm_init);
1237 module_exit(ib_ucm_cleanup);