linux/drivers/infiniband/core/ucma.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2005-2006 Intel Corporation.  All rights reserved.
   3 *
   4 * This software is available to you under a choice of one of two
   5 * licenses.  You may choose to be licensed under the terms of the GNU
   6 * General Public License (GPL) Version 2, available from the file
   7 * COPYING in the main directory of this source tree, or the
   8 * OpenIB.org BSD license below:
   9 *
  10 *     Redistribution and use in source and binary forms, with or
  11 *     without modification, are permitted provided that the following
  12 *     conditions are met:
  13 *
  14 *      - Redistributions of source code must retain the above
  15 *      copyright notice, this list of conditions and the following
  16 *      disclaimer.
  17 *
  18 *      - Redistributions in binary form must reproduce the above
  19 *      copyright notice, this list of conditions and the following
  20 *      disclaimer in the documentation and/or other materials
  21 *      provided with the distribution.
  22 *
  23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  30 * SOFTWARE.
  31 */
  32
  33#include <linux/completion.h>
  34#include <linux/file.h>
  35#include <linux/mutex.h>
  36#include <linux/poll.h>
  37#include <linux/sched.h>
  38#include <linux/idr.h>
  39#include <linux/in.h>
  40#include <linux/in6.h>
  41#include <linux/miscdevice.h>
  42#include <linux/slab.h>
  43#include <linux/sysctl.h>
  44#include <linux/module.h>
  45
  46#include <rdma/rdma_user_cm.h>
  47#include <rdma/ib_marshall.h>
  48#include <rdma/rdma_cm.h>
  49#include <rdma/rdma_cm_ib.h>
  50
  51MODULE_AUTHOR("Sean Hefty");
  52MODULE_DESCRIPTION("RDMA Userspace Connection Manager Access");
  53MODULE_LICENSE("Dual BSD/GPL");
  54
  55static unsigned int max_backlog = 1024;
  56
  57static struct ctl_table_header *ucma_ctl_table_hdr;
  58static ctl_table ucma_ctl_table[] = {
  59        {
  60                .procname       = "max_backlog",
  61                .data           = &max_backlog,
  62                .maxlen         = sizeof max_backlog,
  63                .mode           = 0644,
  64                .proc_handler   = proc_dointvec,
  65        },
  66        { }
  67};
  68
  69static struct ctl_path ucma_ctl_path[] = {
  70        { .procname = "net" },
  71        { .procname = "rdma_ucm" },
  72        { }
  73};
  74
  75struct ucma_file {
  76        struct mutex            mut;
  77        struct file             *filp;
  78        struct list_head        ctx_list;
  79        struct list_head        event_list;
  80        wait_queue_head_t       poll_wait;
  81};
  82
  83struct ucma_context {
  84        int                     id;
  85        struct completion       comp;
  86        atomic_t                ref;
  87        int                     events_reported;
  88        int                     backlog;
  89
  90        struct ucma_file        *file;
  91        struct rdma_cm_id       *cm_id;
  92        u64                     uid;
  93
  94        struct list_head        list;
  95        struct list_head        mc_list;
  96};
  97
  98struct ucma_multicast {
  99        struct ucma_context     *ctx;
 100        int                     id;
 101        int                     events_reported;
 102
 103        u64                     uid;
 104        struct list_head        list;
 105        struct sockaddr_storage addr;
 106};
 107
 108struct ucma_event {
 109        struct ucma_context     *ctx;
 110        struct ucma_multicast   *mc;
 111        struct list_head        list;
 112        struct rdma_cm_id       *cm_id;
 113        struct rdma_ucm_event_resp resp;
 114};
 115
 116static DEFINE_MUTEX(mut);
 117static DEFINE_IDR(ctx_idr);
 118static DEFINE_IDR(multicast_idr);
 119
 120static inline struct ucma_context *_ucma_find_context(int id,
 121                                                      struct ucma_file *file)
 122{
 123        struct ucma_context *ctx;
 124
 125        ctx = idr_find(&ctx_idr, id);
 126        if (!ctx)
 127                ctx = ERR_PTR(-ENOENT);
 128        else if (ctx->file != file)
 129                ctx = ERR_PTR(-EINVAL);
 130        return ctx;
 131}
 132
 133static struct ucma_context *ucma_get_ctx(struct ucma_file *file, int id)
 134{
 135        struct ucma_context *ctx;
 136
 137        mutex_lock(&mut);
 138        ctx = _ucma_find_context(id, file);
 139        if (!IS_ERR(ctx))
 140                atomic_inc(&ctx->ref);
 141        mutex_unlock(&mut);
 142        return ctx;
 143}
 144
 145static void ucma_put_ctx(struct ucma_context *ctx)
 146{
 147        if (atomic_dec_and_test(&ctx->ref))
 148                complete(&ctx->comp);
 149}
 150
 151static struct ucma_context *ucma_alloc_ctx(struct ucma_file *file)
 152{
 153        struct ucma_context *ctx;
 154        int ret;
 155
 156        ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
 157        if (!ctx)
 158                return NULL;
 159
 160        atomic_set(&ctx->ref, 1);
 161        init_completion(&ctx->comp);
 162        INIT_LIST_HEAD(&ctx->mc_list);
 163        ctx->file = file;
 164
 165        do {
 166                ret = idr_pre_get(&ctx_idr, GFP_KERNEL);
 167                if (!ret)
 168                        goto error;
 169
 170                mutex_lock(&mut);
 171                ret = idr_get_new(&ctx_idr, ctx, &ctx->id);
 172                mutex_unlock(&mut);
 173        } while (ret == -EAGAIN);
 174
 175        if (ret)
 176                goto error;
 177
 178        list_add_tail(&ctx->list, &file->ctx_list);
 179        return ctx;
 180
 181error:
 182        kfree(ctx);
 183        return NULL;
 184}
 185
 186static struct ucma_multicast* ucma_alloc_multicast(struct ucma_context *ctx)
 187{
 188        struct ucma_multicast *mc;
 189        int ret;
 190
 191        mc = kzalloc(sizeof(*mc), GFP_KERNEL);
 192        if (!mc)
 193                return NULL;
 194
 195        do {
 196                ret = idr_pre_get(&multicast_idr, GFP_KERNEL);
 197                if (!ret)
 198                        goto error;
 199
 200                mutex_lock(&mut);
 201                ret = idr_get_new(&multicast_idr, mc, &mc->id);
 202                mutex_unlock(&mut);
 203        } while (ret == -EAGAIN);
 204
 205        if (ret)
 206                goto error;
 207
 208        mc->ctx = ctx;
 209        list_add_tail(&mc->list, &ctx->mc_list);
 210        return mc;
 211
 212error:
 213        kfree(mc);
 214        return NULL;
 215}
 216
 217static void ucma_copy_conn_event(struct rdma_ucm_conn_param *dst,
 218                                 struct rdma_conn_param *src)
 219{
 220        if (src->private_data_len)
 221                memcpy(dst->private_data, src->private_data,
 222                       src->private_data_len);
 223        dst->private_data_len = src->private_data_len;
 224        dst->responder_resources =src->responder_resources;
 225        dst->initiator_depth = src->initiator_depth;
 226        dst->flow_control = src->flow_control;
 227        dst->retry_count = src->retry_count;
 228        dst->rnr_retry_count = src->rnr_retry_count;
 229        dst->srq = src->srq;
 230        dst->qp_num = src->qp_num;
 231}
 232
 233static void ucma_copy_ud_event(struct rdma_ucm_ud_param *dst,
 234                               struct rdma_ud_param *src)
 235{
 236        if (src->private_data_len)
 237                memcpy(dst->private_data, src->private_data,
 238                       src->private_data_len);
 239        dst->private_data_len = src->private_data_len;
 240        ib_copy_ah_attr_to_user(&dst->ah_attr, &src->ah_attr);
 241        dst->qp_num = src->qp_num;
 242        dst->qkey = src->qkey;
 243}
 244
 245static void ucma_set_event_context(struct ucma_context *ctx,
 246                                   struct rdma_cm_event *event,
 247                                   struct ucma_event *uevent)
 248{
 249        uevent->ctx = ctx;
 250        switch (event->event) {
 251        case RDMA_CM_EVENT_MULTICAST_JOIN:
 252        case RDMA_CM_EVENT_MULTICAST_ERROR:
 253                uevent->mc = (struct ucma_multicast *)
 254                             event->param.ud.private_data;
 255                uevent->resp.uid = uevent->mc->uid;
 256                uevent->resp.id = uevent->mc->id;
 257                break;
 258        default:
 259                uevent->resp.uid = ctx->uid;
 260                uevent->resp.id = ctx->id;
 261                break;
 262        }
 263}
 264
 265static int ucma_event_handler(struct rdma_cm_id *cm_id,
 266                              struct rdma_cm_event *event)
 267{
 268        struct ucma_event *uevent;
 269        struct ucma_context *ctx = cm_id->context;
 270        int ret = 0;
 271
 272        uevent = kzalloc(sizeof(*uevent), GFP_KERNEL);
 273        if (!uevent)
 274                return event->event == RDMA_CM_EVENT_CONNECT_REQUEST;
 275
 276        uevent->cm_id = cm_id;
 277        ucma_set_event_context(ctx, event, uevent);
 278        uevent->resp.event = event->event;
 279        uevent->resp.status = event->status;
 280        if (cm_id->qp_type == IB_QPT_UD)
 281                ucma_copy_ud_event(&uevent->resp.param.ud, &event->param.ud);
 282        else
 283                ucma_copy_conn_event(&uevent->resp.param.conn,
 284                                     &event->param.conn);
 285
 286        mutex_lock(&ctx->file->mut);
 287        if (event->event == RDMA_CM_EVENT_CONNECT_REQUEST) {
 288                if (!ctx->backlog) {
 289                        ret = -ENOMEM;
 290                        kfree(uevent);
 291                        goto out;
 292                }
 293                ctx->backlog--;
 294        } else if (!ctx->uid) {
 295                /*
 296                 * We ignore events for new connections until userspace has set
 297                 * their context.  This can only happen if an error occurs on a
 298                 * new connection before the user accepts it.  This is okay,
 299                 * since the accept will just fail later.
 300                 */
 301                kfree(uevent);
 302                goto out;
 303        }
 304
 305        list_add_tail(&uevent->list, &ctx->file->event_list);
 306        wake_up_interruptible(&ctx->file->poll_wait);
 307out:
 308        mutex_unlock(&ctx->file->mut);
 309        return ret;
 310}
 311
 312static ssize_t ucma_get_event(struct ucma_file *file, const char __user *inbuf,
 313                              int in_len, int out_len)
 314{
 315        struct ucma_context *ctx;
 316        struct rdma_ucm_get_event cmd;
 317        struct ucma_event *uevent;
 318        int ret = 0;
 319        DEFINE_WAIT(wait);
 320
 321        if (out_len < sizeof uevent->resp)
 322                return -ENOSPC;
 323
 324        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
 325                return -EFAULT;
 326
 327        mutex_lock(&file->mut);
 328        while (list_empty(&file->event_list)) {
 329                mutex_unlock(&file->mut);
 330
 331                if (file->filp->f_flags & O_NONBLOCK)
 332                        return -EAGAIN;
 333
 334                if (wait_event_interruptible(file->poll_wait,
 335                                             !list_empty(&file->event_list)))
 336                        return -ERESTARTSYS;
 337
 338                mutex_lock(&file->mut);
 339        }
 340
 341        uevent = list_entry(file->event_list.next, struct ucma_event, list);
 342
 343        if (uevent->resp.event == RDMA_CM_EVENT_CONNECT_REQUEST) {
 344                ctx = ucma_alloc_ctx(file);
 345                if (!ctx) {
 346                        ret = -ENOMEM;
 347                        goto done;
 348                }
 349                uevent->ctx->backlog++;
 350                ctx->cm_id = uevent->cm_id;
 351                ctx->cm_id->context = ctx;
 352                uevent->resp.id = ctx->id;
 353        }
 354
 355        if (copy_to_user((void __user *)(unsigned long)cmd.response,
 356                         &uevent->resp, sizeof uevent->resp)) {
 357                ret = -EFAULT;
 358                goto done;
 359        }
 360
 361        list_del(&uevent->list);
 362        uevent->ctx->events_reported++;
 363        if (uevent->mc)
 364                uevent->mc->events_reported++;
 365        kfree(uevent);
 366done:
 367        mutex_unlock(&file->mut);
 368        return ret;
 369}
 370
 371static int ucma_get_qp_type(struct rdma_ucm_create_id *cmd, enum ib_qp_type *qp_type)
 372{
 373        switch (cmd->ps) {
 374        case RDMA_PS_TCP:
 375                *qp_type = IB_QPT_RC;
 376                return 0;
 377        case RDMA_PS_UDP:
 378        case RDMA_PS_IPOIB:
 379                *qp_type = IB_QPT_UD;
 380                return 0;
 381        case RDMA_PS_IB:
 382                *qp_type = cmd->qp_type;
 383                return 0;
 384        default:
 385                return -EINVAL;
 386        }
 387}
 388
 389static ssize_t ucma_create_id(struct ucma_file *file, const char __user *inbuf,
 390                              int in_len, int out_len)
 391{
 392        struct rdma_ucm_create_id cmd;
 393        struct rdma_ucm_create_id_resp resp;
 394        struct ucma_context *ctx;
 395        enum ib_qp_type qp_type;
 396        int ret;
 397
 398        if (out_len < sizeof(resp))
 399                return -ENOSPC;
 400
 401        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
 402                return -EFAULT;
 403
 404        ret = ucma_get_qp_type(&cmd, &qp_type);
 405        if (ret)
 406                return ret;
 407
 408        mutex_lock(&file->mut);
 409        ctx = ucma_alloc_ctx(file);
 410        mutex_unlock(&file->mut);
 411        if (!ctx)
 412                return -ENOMEM;
 413
 414        ctx->uid = cmd.uid;
 415        ctx->cm_id = rdma_create_id(ucma_event_handler, ctx, cmd.ps, qp_type);
 416        if (IS_ERR(ctx->cm_id)) {
 417                ret = PTR_ERR(ctx->cm_id);
 418                goto err1;
 419        }
 420
 421        resp.id = ctx->id;
 422        if (copy_to_user((void __user *)(unsigned long)cmd.response,
 423                         &resp, sizeof(resp))) {
 424                ret = -EFAULT;
 425                goto err2;
 426        }
 427        return 0;
 428
 429err2:
 430        rdma_destroy_id(ctx->cm_id);
 431err1:
 432        mutex_lock(&mut);
 433        idr_remove(&ctx_idr, ctx->id);
 434        mutex_unlock(&mut);
 435        kfree(ctx);
 436        return ret;
 437}
 438
 439static void ucma_cleanup_multicast(struct ucma_context *ctx)
 440{
 441        struct ucma_multicast *mc, *tmp;
 442
 443        mutex_lock(&mut);
 444        list_for_each_entry_safe(mc, tmp, &ctx->mc_list, list) {
 445                list_del(&mc->list);
 446                idr_remove(&multicast_idr, mc->id);
 447                kfree(mc);
 448        }
 449        mutex_unlock(&mut);
 450}
 451
 452static void ucma_cleanup_events(struct ucma_context *ctx)
 453{
 454        struct ucma_event *uevent, *tmp;
 455
 456        list_for_each_entry_safe(uevent, tmp, &ctx->file->event_list, list) {
 457                if (uevent->ctx != ctx)
 458                        continue;
 459
 460                list_del(&uevent->list);
 461
 462                /* clear incoming connections. */
 463                if (uevent->resp.event == RDMA_CM_EVENT_CONNECT_REQUEST)
 464                        rdma_destroy_id(uevent->cm_id);
 465
 466                kfree(uevent);
 467        }
 468}
 469
 470static void ucma_cleanup_mc_events(struct ucma_multicast *mc)
 471{
 472        struct ucma_event *uevent, *tmp;
 473
 474        list_for_each_entry_safe(uevent, tmp, &mc->ctx->file->event_list, list) {
 475                if (uevent->mc != mc)
 476                        continue;
 477
 478                list_del(&uevent->list);
 479                kfree(uevent);
 480        }
 481}
 482
 483static int ucma_free_ctx(struct ucma_context *ctx)
 484{
 485        int events_reported;
 486
 487        /* No new events will be generated after destroying the id. */
 488        rdma_destroy_id(ctx->cm_id);
 489
 490        ucma_cleanup_multicast(ctx);
 491
 492        /* Cleanup events not yet reported to the user. */
 493        mutex_lock(&ctx->file->mut);
 494        ucma_cleanup_events(ctx);
 495        list_del(&ctx->list);
 496        mutex_unlock(&ctx->file->mut);
 497
 498        events_reported = ctx->events_reported;
 499        kfree(ctx);
 500        return events_reported;
 501}
 502
 503static ssize_t ucma_destroy_id(struct ucma_file *file, const char __user *inbuf,
 504                               int in_len, int out_len)
 505{
 506        struct rdma_ucm_destroy_id cmd;
 507        struct rdma_ucm_destroy_id_resp resp;
 508        struct ucma_context *ctx;
 509        int ret = 0;
 510
 511        if (out_len < sizeof(resp))
 512                return -ENOSPC;
 513
 514        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
 515                return -EFAULT;
 516
 517        mutex_lock(&mut);
 518        ctx = _ucma_find_context(cmd.id, file);
 519        if (!IS_ERR(ctx))
 520                idr_remove(&ctx_idr, ctx->id);
 521        mutex_unlock(&mut);
 522
 523        if (IS_ERR(ctx))
 524                return PTR_ERR(ctx);
 525
 526        ucma_put_ctx(ctx);
 527        wait_for_completion(&ctx->comp);
 528        resp.events_reported = ucma_free_ctx(ctx);
 529
 530        if (copy_to_user((void __user *)(unsigned long)cmd.response,
 531                         &resp, sizeof(resp)))
 532                ret = -EFAULT;
 533
 534        return ret;
 535}
 536
 537static ssize_t ucma_bind_addr(struct ucma_file *file, const char __user *inbuf,
 538                              int in_len, int out_len)
 539{
 540        struct rdma_ucm_bind_addr cmd;
 541        struct ucma_context *ctx;
 542        int ret;
 543
 544        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
 545                return -EFAULT;
 546
 547        ctx = ucma_get_ctx(file, cmd.id);
 548        if (IS_ERR(ctx))
 549                return PTR_ERR(ctx);
 550
 551        ret = rdma_bind_addr(ctx->cm_id, (struct sockaddr *) &cmd.addr);
 552        ucma_put_ctx(ctx);
 553        return ret;
 554}
 555
 556static ssize_t ucma_resolve_addr(struct ucma_file *file,
 557                                 const char __user *inbuf,
 558                                 int in_len, int out_len)
 559{
 560        struct rdma_ucm_resolve_addr cmd;
 561        struct ucma_context *ctx;
 562        int ret;
 563
 564        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
 565                return -EFAULT;
 566
 567        ctx = ucma_get_ctx(file, cmd.id);
 568        if (IS_ERR(ctx))
 569                return PTR_ERR(ctx);
 570
 571        ret = rdma_resolve_addr(ctx->cm_id, (struct sockaddr *) &cmd.src_addr,
 572                                (struct sockaddr *) &cmd.dst_addr,
 573                                cmd.timeout_ms);
 574        ucma_put_ctx(ctx);
 575        return ret;
 576}
 577
 578static ssize_t ucma_resolve_route(struct ucma_file *file,
 579                                  const char __user *inbuf,
 580                                  int in_len, int out_len)
 581{
 582        struct rdma_ucm_resolve_route cmd;
 583        struct ucma_context *ctx;
 584        int ret;
 585
 586        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
 587                return -EFAULT;
 588
 589        ctx = ucma_get_ctx(file, cmd.id);
 590        if (IS_ERR(ctx))
 591                return PTR_ERR(ctx);
 592
 593        ret = rdma_resolve_route(ctx->cm_id, cmd.timeout_ms);
 594        ucma_put_ctx(ctx);
 595        return ret;
 596}
 597
 598static void ucma_copy_ib_route(struct rdma_ucm_query_route_resp *resp,
 599                               struct rdma_route *route)
 600{
 601        struct rdma_dev_addr *dev_addr;
 602
 603        resp->num_paths = route->num_paths;
 604        switch (route->num_paths) {
 605        case 0:
 606                dev_addr = &route->addr.dev_addr;
 607                rdma_addr_get_dgid(dev_addr,
 608                                   (union ib_gid *) &resp->ib_route[0].dgid);
 609                rdma_addr_get_sgid(dev_addr,
 610                                   (union ib_gid *) &resp->ib_route[0].sgid);
 611                resp->ib_route[0].pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr));
 612                break;
 613        case 2:
 614                ib_copy_path_rec_to_user(&resp->ib_route[1],
 615                                         &route->path_rec[1]);
 616                /* fall through */
 617        case 1:
 618                ib_copy_path_rec_to_user(&resp->ib_route[0],
 619                                         &route->path_rec[0]);
 620                break;
 621        default:
 622                break;
 623        }
 624}
 625
 626static void ucma_copy_iboe_route(struct rdma_ucm_query_route_resp *resp,
 627                                 struct rdma_route *route)
 628{
 629        struct rdma_dev_addr *dev_addr;
 630        struct net_device *dev;
 631        u16 vid = 0;
 632
 633        resp->num_paths = route->num_paths;
 634        switch (route->num_paths) {
 635        case 0:
 636                dev_addr = &route->addr.dev_addr;
 637                dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if);
 638                        if (dev) {
 639                                vid = rdma_vlan_dev_vlan_id(dev);
 640                                dev_put(dev);
 641                        }
 642
 643                iboe_mac_vlan_to_ll((union ib_gid *) &resp->ib_route[0].dgid,
 644                                    dev_addr->dst_dev_addr, vid);
 645                iboe_addr_get_sgid(dev_addr,
 646                                   (union ib_gid *) &resp->ib_route[0].sgid);
 647                resp->ib_route[0].pkey = cpu_to_be16(0xffff);
 648                break;
 649        case 2:
 650                ib_copy_path_rec_to_user(&resp->ib_route[1],
 651                                         &route->path_rec[1]);
 652                /* fall through */
 653        case 1:
 654                ib_copy_path_rec_to_user(&resp->ib_route[0],
 655                                         &route->path_rec[0]);
 656                break;
 657        default:
 658                break;
 659        }
 660}
 661
 662static void ucma_copy_iw_route(struct rdma_ucm_query_route_resp *resp,
 663                               struct rdma_route *route)
 664{
 665        struct rdma_dev_addr *dev_addr;
 666
 667        dev_addr = &route->addr.dev_addr;
 668        rdma_addr_get_dgid(dev_addr, (union ib_gid *) &resp->ib_route[0].dgid);
 669        rdma_addr_get_sgid(dev_addr, (union ib_gid *) &resp->ib_route[0].sgid);
 670}
 671
 672static ssize_t ucma_query_route(struct ucma_file *file,
 673                                const char __user *inbuf,
 674                                int in_len, int out_len)
 675{
 676        struct rdma_ucm_query_route cmd;
 677        struct rdma_ucm_query_route_resp resp;
 678        struct ucma_context *ctx;
 679        struct sockaddr *addr;
 680        int ret = 0;
 681
 682        if (out_len < sizeof(resp))
 683                return -ENOSPC;
 684
 685        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
 686                return -EFAULT;
 687
 688        ctx = ucma_get_ctx(file, cmd.id);
 689        if (IS_ERR(ctx))
 690                return PTR_ERR(ctx);
 691
 692        memset(&resp, 0, sizeof resp);
 693        addr = (struct sockaddr *) &ctx->cm_id->route.addr.src_addr;
 694        memcpy(&resp.src_addr, addr, addr->sa_family == AF_INET ?
 695                                     sizeof(struct sockaddr_in) :
 696                                     sizeof(struct sockaddr_in6));
 697        addr = (struct sockaddr *) &ctx->cm_id->route.addr.dst_addr;
 698        memcpy(&resp.dst_addr, addr, addr->sa_family == AF_INET ?
 699                                     sizeof(struct sockaddr_in) :
 700                                     sizeof(struct sockaddr_in6));
 701        if (!ctx->cm_id->device)
 702                goto out;
 703
 704        resp.node_guid = (__force __u64) ctx->cm_id->device->node_guid;
 705        resp.port_num = ctx->cm_id->port_num;
 706        switch (rdma_node_get_transport(ctx->cm_id->device->node_type)) {
 707        case RDMA_TRANSPORT_IB:
 708                switch (rdma_port_get_link_layer(ctx->cm_id->device,
 709                        ctx->cm_id->port_num)) {
 710                case IB_LINK_LAYER_INFINIBAND:
 711                        ucma_copy_ib_route(&resp, &ctx->cm_id->route);
 712                        break;
 713                case IB_LINK_LAYER_ETHERNET:
 714                        ucma_copy_iboe_route(&resp, &ctx->cm_id->route);
 715                        break;
 716                default:
 717                        break;
 718                }
 719                break;
 720        case RDMA_TRANSPORT_IWARP:
 721                ucma_copy_iw_route(&resp, &ctx->cm_id->route);
 722                break;
 723        default:
 724                break;
 725        }
 726
 727out:
 728        if (copy_to_user((void __user *)(unsigned long)cmd.response,
 729                         &resp, sizeof(resp)))
 730                ret = -EFAULT;
 731
 732        ucma_put_ctx(ctx);
 733        return ret;
 734}
 735
 736static void ucma_copy_conn_param(struct rdma_conn_param *dst,
 737                                 struct rdma_ucm_conn_param *src)
 738{
 739        dst->private_data = src->private_data;
 740        dst->private_data_len = src->private_data_len;
 741        dst->responder_resources =src->responder_resources;
 742        dst->initiator_depth = src->initiator_depth;
 743        dst->flow_control = src->flow_control;
 744        dst->retry_count = src->retry_count;
 745        dst->rnr_retry_count = src->rnr_retry_count;
 746        dst->srq = src->srq;
 747        dst->qp_num = src->qp_num;
 748}
 749
 750static ssize_t ucma_connect(struct ucma_file *file, const char __user *inbuf,
 751                            int in_len, int out_len)
 752{
 753        struct rdma_ucm_connect cmd;
 754        struct rdma_conn_param conn_param;
 755        struct ucma_context *ctx;
 756        int ret;
 757
 758        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
 759                return -EFAULT;
 760
 761        if (!cmd.conn_param.valid)
 762                return -EINVAL;
 763
 764        ctx = ucma_get_ctx(file, cmd.id);
 765        if (IS_ERR(ctx))
 766                return PTR_ERR(ctx);
 767
 768        ucma_copy_conn_param(&conn_param, &cmd.conn_param);
 769        ret = rdma_connect(ctx->cm_id, &conn_param);
 770        ucma_put_ctx(ctx);
 771        return ret;
 772}
 773
 774static ssize_t ucma_listen(struct ucma_file *file, const char __user *inbuf,
 775                           int in_len, int out_len)
 776{
 777        struct rdma_ucm_listen cmd;
 778        struct ucma_context *ctx;
 779        int ret;
 780
 781        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
 782                return -EFAULT;
 783
 784        ctx = ucma_get_ctx(file, cmd.id);
 785        if (IS_ERR(ctx))
 786                return PTR_ERR(ctx);
 787
 788        ctx->backlog = cmd.backlog > 0 && cmd.backlog < max_backlog ?
 789                       cmd.backlog : max_backlog;
 790        ret = rdma_listen(ctx->cm_id, ctx->backlog);
 791        ucma_put_ctx(ctx);
 792        return ret;
 793}
 794
 795static ssize_t ucma_accept(struct ucma_file *file, const char __user *inbuf,
 796                           int in_len, int out_len)
 797{
 798        struct rdma_ucm_accept cmd;
 799        struct rdma_conn_param conn_param;
 800        struct ucma_context *ctx;
 801        int ret;
 802
 803        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
 804                return -EFAULT;
 805
 806        ctx = ucma_get_ctx(file, cmd.id);
 807        if (IS_ERR(ctx))
 808                return PTR_ERR(ctx);
 809
 810        if (cmd.conn_param.valid) {
 811                ucma_copy_conn_param(&conn_param, &cmd.conn_param);
 812                mutex_lock(&file->mut);
 813                ret = rdma_accept(ctx->cm_id, &conn_param);
 814                if (!ret)
 815                        ctx->uid = cmd.uid;
 816                mutex_unlock(&file->mut);
 817        } else
 818                ret = rdma_accept(ctx->cm_id, NULL);
 819
 820        ucma_put_ctx(ctx);
 821        return ret;
 822}
 823
 824static ssize_t ucma_reject(struct ucma_file *file, const char __user *inbuf,
 825                           int in_len, int out_len)
 826{
 827        struct rdma_ucm_reject cmd;
 828        struct ucma_context *ctx;
 829        int ret;
 830
 831        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
 832                return -EFAULT;
 833
 834        ctx = ucma_get_ctx(file, cmd.id);
 835        if (IS_ERR(ctx))
 836                return PTR_ERR(ctx);
 837
 838        ret = rdma_reject(ctx->cm_id, cmd.private_data, cmd.private_data_len);
 839        ucma_put_ctx(ctx);
 840        return ret;
 841}
 842
 843static ssize_t ucma_disconnect(struct ucma_file *file, const char __user *inbuf,
 844                               int in_len, int out_len)
 845{
 846        struct rdma_ucm_disconnect cmd;
 847        struct ucma_context *ctx;
 848        int ret;
 849
 850        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
 851                return -EFAULT;
 852
 853        ctx = ucma_get_ctx(file, cmd.id);
 854        if (IS_ERR(ctx))
 855                return PTR_ERR(ctx);
 856
 857        ret = rdma_disconnect(ctx->cm_id);
 858        ucma_put_ctx(ctx);
 859        return ret;
 860}
 861
 862static ssize_t ucma_init_qp_attr(struct ucma_file *file,
 863                                 const char __user *inbuf,
 864                                 int in_len, int out_len)
 865{
 866        struct rdma_ucm_init_qp_attr cmd;
 867        struct ib_uverbs_qp_attr resp;
 868        struct ucma_context *ctx;
 869        struct ib_qp_attr qp_attr;
 870        int ret;
 871
 872        if (out_len < sizeof(resp))
 873                return -ENOSPC;
 874
 875        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
 876                return -EFAULT;
 877
 878        ctx = ucma_get_ctx(file, cmd.id);
 879        if (IS_ERR(ctx))
 880                return PTR_ERR(ctx);
 881
 882        resp.qp_attr_mask = 0;
 883        memset(&qp_attr, 0, sizeof qp_attr);
 884        qp_attr.qp_state = cmd.qp_state;
 885        ret = rdma_init_qp_attr(ctx->cm_id, &qp_attr, &resp.qp_attr_mask);
 886        if (ret)
 887                goto out;
 888
 889        ib_copy_qp_attr_to_user(&resp, &qp_attr);
 890        if (copy_to_user((void __user *)(unsigned long)cmd.response,
 891                         &resp, sizeof(resp)))
 892                ret = -EFAULT;
 893
 894out:
 895        ucma_put_ctx(ctx);
 896        return ret;
 897}
 898
 899static int ucma_set_option_id(struct ucma_context *ctx, int optname,
 900                              void *optval, size_t optlen)
 901{
 902        int ret = 0;
 903
 904        switch (optname) {
 905        case RDMA_OPTION_ID_TOS:
 906                if (optlen != sizeof(u8)) {
 907                        ret = -EINVAL;
 908                        break;
 909                }
 910                rdma_set_service_type(ctx->cm_id, *((u8 *) optval));
 911                break;
 912        case RDMA_OPTION_ID_REUSEADDR:
 913                if (optlen != sizeof(int)) {
 914                        ret = -EINVAL;
 915                        break;
 916                }
 917                ret = rdma_set_reuseaddr(ctx->cm_id, *((int *) optval) ? 1 : 0);
 918                break;
 919        default:
 920                ret = -ENOSYS;
 921        }
 922
 923        return ret;
 924}
 925
 926static int ucma_set_ib_path(struct ucma_context *ctx,
 927                            struct ib_path_rec_data *path_data, size_t optlen)
 928{
 929        struct ib_sa_path_rec sa_path;
 930        struct rdma_cm_event event;
 931        int ret;
 932
 933        if (optlen % sizeof(*path_data))
 934                return -EINVAL;
 935
 936        for (; optlen; optlen -= sizeof(*path_data), path_data++) {
 937                if (path_data->flags == (IB_PATH_GMP | IB_PATH_PRIMARY |
 938                                         IB_PATH_BIDIRECTIONAL))
 939                        break;
 940        }
 941
 942        if (!optlen)
 943                return -EINVAL;
 944
 945        ib_sa_unpack_path(path_data->path_rec, &sa_path);
 946        ret = rdma_set_ib_paths(ctx->cm_id, &sa_path, 1);
 947        if (ret)
 948                return ret;
 949
 950        memset(&event, 0, sizeof event);
 951        event.event = RDMA_CM_EVENT_ROUTE_RESOLVED;
 952        return ucma_event_handler(ctx->cm_id, &event);
 953}
 954
 955static int ucma_set_option_ib(struct ucma_context *ctx, int optname,
 956                              void *optval, size_t optlen)
 957{
 958        int ret;
 959
 960        switch (optname) {
 961        case RDMA_OPTION_IB_PATH:
 962                ret = ucma_set_ib_path(ctx, optval, optlen);
 963                break;
 964        default:
 965                ret = -ENOSYS;
 966        }
 967
 968        return ret;
 969}
 970
 971static int ucma_set_option_level(struct ucma_context *ctx, int level,
 972                                 int optname, void *optval, size_t optlen)
 973{
 974        int ret;
 975
 976        switch (level) {
 977        case RDMA_OPTION_ID:
 978                ret = ucma_set_option_id(ctx, optname, optval, optlen);
 979                break;
 980        case RDMA_OPTION_IB:
 981                ret = ucma_set_option_ib(ctx, optname, optval, optlen);
 982                break;
 983        default:
 984                ret = -ENOSYS;
 985        }
 986
 987        return ret;
 988}
 989
 990static ssize_t ucma_set_option(struct ucma_file *file, const char __user *inbuf,
 991                               int in_len, int out_len)
 992{
 993        struct rdma_ucm_set_option cmd;
 994        struct ucma_context *ctx;
 995        void *optval;
 996        int ret;
 997
 998        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
 999                return -EFAULT;
1000
1001        ctx = ucma_get_ctx(file, cmd.id);
1002        if (IS_ERR(ctx))
1003                return PTR_ERR(ctx);
1004
1005        optval = kmalloc(cmd.optlen, GFP_KERNEL);
1006        if (!optval) {
1007                ret = -ENOMEM;
1008                goto out1;
1009        }
1010
1011        if (copy_from_user(optval, (void __user *) (unsigned long) cmd.optval,
1012                           cmd.optlen)) {
1013                ret = -EFAULT;
1014                goto out2;
1015        }
1016
1017        ret = ucma_set_option_level(ctx, cmd.level, cmd.optname, optval,
1018                                    cmd.optlen);
1019out2:
1020        kfree(optval);
1021out1:
1022        ucma_put_ctx(ctx);
1023        return ret;
1024}
1025
1026static ssize_t ucma_notify(struct ucma_file *file, const char __user *inbuf,
1027                           int in_len, int out_len)
1028{
1029        struct rdma_ucm_notify cmd;
1030        struct ucma_context *ctx;
1031        int ret;
1032
1033        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
1034                return -EFAULT;
1035
1036        ctx = ucma_get_ctx(file, cmd.id);
1037        if (IS_ERR(ctx))
1038                return PTR_ERR(ctx);
1039
1040        ret = rdma_notify(ctx->cm_id, (enum ib_event_type) cmd.event);
1041        ucma_put_ctx(ctx);
1042        return ret;
1043}
1044
1045static ssize_t ucma_join_multicast(struct ucma_file *file,
1046                                   const char __user *inbuf,
1047                                   int in_len, int out_len)
1048{
1049        struct rdma_ucm_join_mcast cmd;
1050        struct rdma_ucm_create_id_resp resp;
1051        struct ucma_context *ctx;
1052        struct ucma_multicast *mc;
1053        int ret;
1054
1055        if (out_len < sizeof(resp))
1056                return -ENOSPC;
1057
1058        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
1059                return -EFAULT;
1060
1061        ctx = ucma_get_ctx(file, cmd.id);
1062        if (IS_ERR(ctx))
1063                return PTR_ERR(ctx);
1064
1065        mutex_lock(&file->mut);
1066        mc = ucma_alloc_multicast(ctx);
1067        if (!mc) {
1068                ret = -ENOMEM;
1069                goto err1;
1070        }
1071
1072        mc->uid = cmd.uid;
1073        memcpy(&mc->addr, &cmd.addr, sizeof cmd.addr);
1074        ret = rdma_join_multicast(ctx->cm_id, (struct sockaddr *) &mc->addr, mc);
1075        if (ret)
1076                goto err2;
1077
1078        resp.id = mc->id;
1079        if (copy_to_user((void __user *)(unsigned long)cmd.response,
1080                         &resp, sizeof(resp))) {
1081                ret = -EFAULT;
1082                goto err3;
1083        }
1084
1085        mutex_unlock(&file->mut);
1086        ucma_put_ctx(ctx);
1087        return 0;
1088
1089err3:
1090        rdma_leave_multicast(ctx->cm_id, (struct sockaddr *) &mc->addr);
1091        ucma_cleanup_mc_events(mc);
1092err2:
1093        mutex_lock(&mut);
1094        idr_remove(&multicast_idr, mc->id);
1095        mutex_unlock(&mut);
1096        list_del(&mc->list);
1097        kfree(mc);
1098err1:
1099        mutex_unlock(&file->mut);
1100        ucma_put_ctx(ctx);
1101        return ret;
1102}
1103
1104static ssize_t ucma_leave_multicast(struct ucma_file *file,
1105                                    const char __user *inbuf,
1106                                    int in_len, int out_len)
1107{
1108        struct rdma_ucm_destroy_id cmd;
1109        struct rdma_ucm_destroy_id_resp resp;
1110        struct ucma_multicast *mc;
1111        int ret = 0;
1112
1113        if (out_len < sizeof(resp))
1114                return -ENOSPC;
1115
1116        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
1117                return -EFAULT;
1118
1119        mutex_lock(&mut);
1120        mc = idr_find(&multicast_idr, cmd.id);
1121        if (!mc)
1122                mc = ERR_PTR(-ENOENT);
1123        else if (mc->ctx->file != file)
1124                mc = ERR_PTR(-EINVAL);
1125        else {
1126                idr_remove(&multicast_idr, mc->id);
1127                atomic_inc(&mc->ctx->ref);
1128        }
1129        mutex_unlock(&mut);
1130
1131        if (IS_ERR(mc)) {
1132                ret = PTR_ERR(mc);
1133                goto out;
1134        }
1135
1136        rdma_leave_multicast(mc->ctx->cm_id, (struct sockaddr *) &mc->addr);
1137        mutex_lock(&mc->ctx->file->mut);
1138        ucma_cleanup_mc_events(mc);
1139        list_del(&mc->list);
1140        mutex_unlock(&mc->ctx->file->mut);
1141
1142        ucma_put_ctx(mc->ctx);
1143        resp.events_reported = mc->events_reported;
1144        kfree(mc);
1145
1146        if (copy_to_user((void __user *)(unsigned long)cmd.response,
1147                         &resp, sizeof(resp)))
1148                ret = -EFAULT;
1149out:
1150        return ret;
1151}
1152
1153static void ucma_lock_files(struct ucma_file *file1, struct ucma_file *file2)
1154{
1155        /* Acquire mutex's based on pointer comparison to prevent deadlock. */
1156        if (file1 < file2) {
1157                mutex_lock(&file1->mut);
1158                mutex_lock(&file2->mut);
1159        } else {
1160                mutex_lock(&file2->mut);
1161                mutex_lock(&file1->mut);
1162        }
1163}
1164
1165static void ucma_unlock_files(struct ucma_file *file1, struct ucma_file *file2)
1166{
1167        if (file1 < file2) {
1168                mutex_unlock(&file2->mut);
1169                mutex_unlock(&file1->mut);
1170        } else {
1171                mutex_unlock(&file1->mut);
1172                mutex_unlock(&file2->mut);
1173        }
1174}
1175
1176static void ucma_move_events(struct ucma_context *ctx, struct ucma_file *file)
1177{
1178        struct ucma_event *uevent, *tmp;
1179
1180        list_for_each_entry_safe(uevent, tmp, &ctx->file->event_list, list)
1181                if (uevent->ctx == ctx)
1182                        list_move_tail(&uevent->list, &file->event_list);
1183}
1184
1185static ssize_t ucma_migrate_id(struct ucma_file *new_file,
1186                               const char __user *inbuf,
1187                               int in_len, int out_len)
1188{
1189        struct rdma_ucm_migrate_id cmd;
1190        struct rdma_ucm_migrate_resp resp;
1191        struct ucma_context *ctx;
1192        struct file *filp;
1193        struct ucma_file *cur_file;
1194        int ret = 0;
1195
1196        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
1197                return -EFAULT;
1198
1199        /* Get current fd to protect against it being closed */
1200        filp = fget(cmd.fd);
1201        if (!filp)
1202                return -ENOENT;
1203
1204        /* Validate current fd and prevent destruction of id. */
1205        ctx = ucma_get_ctx(filp->private_data, cmd.id);
1206        if (IS_ERR(ctx)) {
1207                ret = PTR_ERR(ctx);
1208                goto file_put;
1209        }
1210
1211        cur_file = ctx->file;
1212        if (cur_file == new_file) {
1213                resp.events_reported = ctx->events_reported;
1214                goto response;
1215        }
1216
1217        /*
1218         * Migrate events between fd's, maintaining order, and avoiding new
1219         * events being added before existing events.
1220         */
1221        ucma_lock_files(cur_file, new_file);
1222        mutex_lock(&mut);
1223
1224        list_move_tail(&ctx->list, &new_file->ctx_list);
1225        ucma_move_events(ctx, new_file);
1226        ctx->file = new_file;
1227        resp.events_reported = ctx->events_reported;
1228
1229        mutex_unlock(&mut);
1230        ucma_unlock_files(cur_file, new_file);
1231
1232response:
1233        if (copy_to_user((void __user *)(unsigned long)cmd.response,
1234                         &resp, sizeof(resp)))
1235                ret = -EFAULT;
1236
1237        ucma_put_ctx(ctx);
1238file_put:
1239        fput(filp);
1240        return ret;
1241}
1242
1243static ssize_t (*ucma_cmd_table[])(struct ucma_file *file,
1244                                   const char __user *inbuf,
1245                                   int in_len, int out_len) = {
1246        [RDMA_USER_CM_CMD_CREATE_ID]    = ucma_create_id,
1247        [RDMA_USER_CM_CMD_DESTROY_ID]   = ucma_destroy_id,
1248        [RDMA_USER_CM_CMD_BIND_ADDR]    = ucma_bind_addr,
1249        [RDMA_USER_CM_CMD_RESOLVE_ADDR] = ucma_resolve_addr,
1250        [RDMA_USER_CM_CMD_RESOLVE_ROUTE]= ucma_resolve_route,
1251        [RDMA_USER_CM_CMD_QUERY_ROUTE]  = ucma_query_route,
1252        [RDMA_USER_CM_CMD_CONNECT]      = ucma_connect,
1253        [RDMA_USER_CM_CMD_LISTEN]       = ucma_listen,
1254        [RDMA_USER_CM_CMD_ACCEPT]       = ucma_accept,
1255        [RDMA_USER_CM_CMD_REJECT]       = ucma_reject,
1256        [RDMA_USER_CM_CMD_DISCONNECT]   = ucma_disconnect,
1257        [RDMA_USER_CM_CMD_INIT_QP_ATTR] = ucma_init_qp_attr,
1258        [RDMA_USER_CM_CMD_GET_EVENT]    = ucma_get_event,
1259        [RDMA_USER_CM_CMD_GET_OPTION]   = NULL,
1260        [RDMA_USER_CM_CMD_SET_OPTION]   = ucma_set_option,
1261        [RDMA_USER_CM_CMD_NOTIFY]       = ucma_notify,
1262        [RDMA_USER_CM_CMD_JOIN_MCAST]   = ucma_join_multicast,
1263        [RDMA_USER_CM_CMD_LEAVE_MCAST]  = ucma_leave_multicast,
1264        [RDMA_USER_CM_CMD_MIGRATE_ID]   = ucma_migrate_id
1265};
1266
1267static ssize_t ucma_write(struct file *filp, const char __user *buf,
1268                          size_t len, loff_t *pos)
1269{
1270        struct ucma_file *file = filp->private_data;
1271        struct rdma_ucm_cmd_hdr hdr;
1272        ssize_t ret;
1273
1274        if (len < sizeof(hdr))
1275                return -EINVAL;
1276
1277        if (copy_from_user(&hdr, buf, sizeof(hdr)))
1278                return -EFAULT;
1279
1280        if (hdr.cmd >= ARRAY_SIZE(ucma_cmd_table))
1281                return -EINVAL;
1282
1283        if (hdr.in + sizeof(hdr) > len)
1284                return -EINVAL;
1285
1286        if (!ucma_cmd_table[hdr.cmd])
1287                return -ENOSYS;
1288
1289        ret = ucma_cmd_table[hdr.cmd](file, buf + sizeof(hdr), hdr.in, hdr.out);
1290        if (!ret)
1291                ret = len;
1292
1293        return ret;
1294}
1295
1296static unsigned int ucma_poll(struct file *filp, struct poll_table_struct *wait)
1297{
1298        struct ucma_file *file = filp->private_data;
1299        unsigned int mask = 0;
1300
1301        poll_wait(filp, &file->poll_wait, wait);
1302
1303        if (!list_empty(&file->event_list))
1304                mask = POLLIN | POLLRDNORM;
1305
1306        return mask;
1307}
1308
1309/*
1310 * ucma_open() does not need the BKL:
1311 *
1312 *  - no global state is referred to;
1313 *  - there is no ioctl method to race against;
1314 *  - no further module initialization is required for open to work
1315 *    after the device is registered.
1316 */
1317static int ucma_open(struct inode *inode, struct file *filp)
1318{
1319        struct ucma_file *file;
1320
1321        file = kmalloc(sizeof *file, GFP_KERNEL);
1322        if (!file)
1323                return -ENOMEM;
1324
1325        INIT_LIST_HEAD(&file->event_list);
1326        INIT_LIST_HEAD(&file->ctx_list);
1327        init_waitqueue_head(&file->poll_wait);
1328        mutex_init(&file->mut);
1329
1330        filp->private_data = file;
1331        file->filp = filp;
1332
1333        return nonseekable_open(inode, filp);
1334}
1335
1336static int ucma_close(struct inode *inode, struct file *filp)
1337{
1338        struct ucma_file *file = filp->private_data;
1339        struct ucma_context *ctx, *tmp;
1340
1341        mutex_lock(&file->mut);
1342        list_for_each_entry_safe(ctx, tmp, &file->ctx_list, list) {
1343                mutex_unlock(&file->mut);
1344
1345                mutex_lock(&mut);
1346                idr_remove(&ctx_idr, ctx->id);
1347                mutex_unlock(&mut);
1348
1349                ucma_free_ctx(ctx);
1350                mutex_lock(&file->mut);
1351        }
1352        mutex_unlock(&file->mut);
1353        kfree(file);
1354        return 0;
1355}
1356
1357static const struct file_operations ucma_fops = {
1358        .owner   = THIS_MODULE,
1359        .open    = ucma_open,
1360        .release = ucma_close,
1361        .write   = ucma_write,
1362        .poll    = ucma_poll,
1363        .llseek  = no_llseek,
1364};
1365
1366static struct miscdevice ucma_misc = {
1367        .minor          = MISC_DYNAMIC_MINOR,
1368        .name           = "rdma_cm",
1369        .nodename       = "infiniband/rdma_cm",
1370        .mode           = 0666,
1371        .fops           = &ucma_fops,
1372};
1373
1374static ssize_t show_abi_version(struct device *dev,
1375                                struct device_attribute *attr,
1376                                char *buf)
1377{
1378        return sprintf(buf, "%d\n", RDMA_USER_CM_ABI_VERSION);
1379}
1380static DEVICE_ATTR(abi_version, S_IRUGO, show_abi_version, NULL);
1381
1382static int __init ucma_init(void)
1383{
1384        int ret;
1385
1386        ret = misc_register(&ucma_misc);
1387        if (ret)
1388                return ret;
1389
1390        ret = device_create_file(ucma_misc.this_device, &dev_attr_abi_version);
1391        if (ret) {
1392                printk(KERN_ERR "rdma_ucm: couldn't create abi_version attr\n");
1393                goto err1;
1394        }
1395
1396        ucma_ctl_table_hdr = register_sysctl_paths(ucma_ctl_path, ucma_ctl_table);
1397        if (!ucma_ctl_table_hdr) {
1398                printk(KERN_ERR "rdma_ucm: couldn't register sysctl paths\n");
1399                ret = -ENOMEM;
1400                goto err2;
1401        }
1402        return 0;
1403err2:
1404        device_remove_file(ucma_misc.this_device, &dev_attr_abi_version);
1405err1:
1406        misc_deregister(&ucma_misc);
1407        return ret;
1408}
1409
1410static void __exit ucma_cleanup(void)
1411{
1412        unregister_sysctl_table(ucma_ctl_table_hdr);
1413        device_remove_file(ucma_misc.this_device, &dev_attr_abi_version);
1414        misc_deregister(&ucma_misc);
1415        idr_destroy(&ctx_idr);
1416}
1417
1418module_init(ucma_init);
1419module_exit(ucma_cleanup);
1420