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                ctx->uid = cmd.uid;
 812                ucma_copy_conn_param(&conn_param, &cmd.conn_param);
 813                ret = rdma_accept(ctx->cm_id, &conn_param);
 814        } else
 815                ret = rdma_accept(ctx->cm_id, NULL);
 816
 817        ucma_put_ctx(ctx);
 818        return ret;
 819}
 820
 821static ssize_t ucma_reject(struct ucma_file *file, const char __user *inbuf,
 822                           int in_len, int out_len)
 823{
 824        struct rdma_ucm_reject cmd;
 825        struct ucma_context *ctx;
 826        int ret;
 827
 828        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
 829                return -EFAULT;
 830
 831        ctx = ucma_get_ctx(file, cmd.id);
 832        if (IS_ERR(ctx))
 833                return PTR_ERR(ctx);
 834
 835        ret = rdma_reject(ctx->cm_id, cmd.private_data, cmd.private_data_len);
 836        ucma_put_ctx(ctx);
 837        return ret;
 838}
 839
 840static ssize_t ucma_disconnect(struct ucma_file *file, const char __user *inbuf,
 841                               int in_len, int out_len)
 842{
 843        struct rdma_ucm_disconnect cmd;
 844        struct ucma_context *ctx;
 845        int ret;
 846
 847        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
 848                return -EFAULT;
 849
 850        ctx = ucma_get_ctx(file, cmd.id);
 851        if (IS_ERR(ctx))
 852                return PTR_ERR(ctx);
 853
 854        ret = rdma_disconnect(ctx->cm_id);
 855        ucma_put_ctx(ctx);
 856        return ret;
 857}
 858
 859static ssize_t ucma_init_qp_attr(struct ucma_file *file,
 860                                 const char __user *inbuf,
 861                                 int in_len, int out_len)
 862{
 863        struct rdma_ucm_init_qp_attr cmd;
 864        struct ib_uverbs_qp_attr resp;
 865        struct ucma_context *ctx;
 866        struct ib_qp_attr qp_attr;
 867        int ret;
 868
 869        if (out_len < sizeof(resp))
 870                return -ENOSPC;
 871
 872        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
 873                return -EFAULT;
 874
 875        ctx = ucma_get_ctx(file, cmd.id);
 876        if (IS_ERR(ctx))
 877                return PTR_ERR(ctx);
 878
 879        resp.qp_attr_mask = 0;
 880        memset(&qp_attr, 0, sizeof qp_attr);
 881        qp_attr.qp_state = cmd.qp_state;
 882        ret = rdma_init_qp_attr(ctx->cm_id, &qp_attr, &resp.qp_attr_mask);
 883        if (ret)
 884                goto out;
 885
 886        ib_copy_qp_attr_to_user(&resp, &qp_attr);
 887        if (copy_to_user((void __user *)(unsigned long)cmd.response,
 888                         &resp, sizeof(resp)))
 889                ret = -EFAULT;
 890
 891out:
 892        ucma_put_ctx(ctx);
 893        return ret;
 894}
 895
 896static int ucma_set_option_id(struct ucma_context *ctx, int optname,
 897                              void *optval, size_t optlen)
 898{
 899        int ret = 0;
 900
 901        switch (optname) {
 902        case RDMA_OPTION_ID_TOS:
 903                if (optlen != sizeof(u8)) {
 904                        ret = -EINVAL;
 905                        break;
 906                }
 907                rdma_set_service_type(ctx->cm_id, *((u8 *) optval));
 908                break;
 909        case RDMA_OPTION_ID_REUSEADDR:
 910                if (optlen != sizeof(int)) {
 911                        ret = -EINVAL;
 912                        break;
 913                }
 914                ret = rdma_set_reuseaddr(ctx->cm_id, *((int *) optval) ? 1 : 0);
 915                break;
 916        default:
 917                ret = -ENOSYS;
 918        }
 919
 920        return ret;
 921}
 922
 923static int ucma_set_ib_path(struct ucma_context *ctx,
 924                            struct ib_path_rec_data *path_data, size_t optlen)
 925{
 926        struct ib_sa_path_rec sa_path;
 927        struct rdma_cm_event event;
 928        int ret;
 929
 930        if (optlen % sizeof(*path_data))
 931                return -EINVAL;
 932
 933        for (; optlen; optlen -= sizeof(*path_data), path_data++) {
 934                if (path_data->flags == (IB_PATH_GMP | IB_PATH_PRIMARY |
 935                                         IB_PATH_BIDIRECTIONAL))
 936                        break;
 937        }
 938
 939        if (!optlen)
 940                return -EINVAL;
 941
 942        ib_sa_unpack_path(path_data->path_rec, &sa_path);
 943        ret = rdma_set_ib_paths(ctx->cm_id, &sa_path, 1);
 944        if (ret)
 945                return ret;
 946
 947        memset(&event, 0, sizeof event);
 948        event.event = RDMA_CM_EVENT_ROUTE_RESOLVED;
 949        return ucma_event_handler(ctx->cm_id, &event);
 950}
 951
 952static int ucma_set_option_ib(struct ucma_context *ctx, int optname,
 953                              void *optval, size_t optlen)
 954{
 955        int ret;
 956
 957        switch (optname) {
 958        case RDMA_OPTION_IB_PATH:
 959                ret = ucma_set_ib_path(ctx, optval, optlen);
 960                break;
 961        default:
 962                ret = -ENOSYS;
 963        }
 964
 965        return ret;
 966}
 967
 968static int ucma_set_option_level(struct ucma_context *ctx, int level,
 969                                 int optname, void *optval, size_t optlen)
 970{
 971        int ret;
 972
 973        switch (level) {
 974        case RDMA_OPTION_ID:
 975                ret = ucma_set_option_id(ctx, optname, optval, optlen);
 976                break;
 977        case RDMA_OPTION_IB:
 978                ret = ucma_set_option_ib(ctx, optname, optval, optlen);
 979                break;
 980        default:
 981                ret = -ENOSYS;
 982        }
 983
 984        return ret;
 985}
 986
 987static ssize_t ucma_set_option(struct ucma_file *file, const char __user *inbuf,
 988                               int in_len, int out_len)
 989{
 990        struct rdma_ucm_set_option cmd;
 991        struct ucma_context *ctx;
 992        void *optval;
 993        int ret;
 994
 995        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
 996                return -EFAULT;
 997
 998        ctx = ucma_get_ctx(file, cmd.id);
 999        if (IS_ERR(ctx))
1000                return PTR_ERR(ctx);
1001
1002        optval = kmalloc(cmd.optlen, GFP_KERNEL);
1003        if (!optval) {
1004                ret = -ENOMEM;
1005                goto out1;
1006        }
1007
1008        if (copy_from_user(optval, (void __user *) (unsigned long) cmd.optval,
1009                           cmd.optlen)) {
1010                ret = -EFAULT;
1011                goto out2;
1012        }
1013
1014        ret = ucma_set_option_level(ctx, cmd.level, cmd.optname, optval,
1015                                    cmd.optlen);
1016out2:
1017        kfree(optval);
1018out1:
1019        ucma_put_ctx(ctx);
1020        return ret;
1021}
1022
1023static ssize_t ucma_notify(struct ucma_file *file, const char __user *inbuf,
1024                           int in_len, int out_len)
1025{
1026        struct rdma_ucm_notify cmd;
1027        struct ucma_context *ctx;
1028        int ret;
1029
1030        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
1031                return -EFAULT;
1032
1033        ctx = ucma_get_ctx(file, cmd.id);
1034        if (IS_ERR(ctx))
1035                return PTR_ERR(ctx);
1036
1037        ret = rdma_notify(ctx->cm_id, (enum ib_event_type) cmd.event);
1038        ucma_put_ctx(ctx);
1039        return ret;
1040}
1041
1042static ssize_t ucma_join_multicast(struct ucma_file *file,
1043                                   const char __user *inbuf,
1044                                   int in_len, int out_len)
1045{
1046        struct rdma_ucm_join_mcast cmd;
1047        struct rdma_ucm_create_id_resp resp;
1048        struct ucma_context *ctx;
1049        struct ucma_multicast *mc;
1050        int ret;
1051
1052        if (out_len < sizeof(resp))
1053                return -ENOSPC;
1054
1055        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
1056                return -EFAULT;
1057
1058        ctx = ucma_get_ctx(file, cmd.id);
1059        if (IS_ERR(ctx))
1060                return PTR_ERR(ctx);
1061
1062        mutex_lock(&file->mut);
1063        mc = ucma_alloc_multicast(ctx);
1064        if (!mc) {
1065                ret = -ENOMEM;
1066                goto err1;
1067        }
1068
1069        mc->uid = cmd.uid;
1070        memcpy(&mc->addr, &cmd.addr, sizeof cmd.addr);
1071        ret = rdma_join_multicast(ctx->cm_id, (struct sockaddr *) &mc->addr, mc);
1072        if (ret)
1073                goto err2;
1074
1075        resp.id = mc->id;
1076        if (copy_to_user((void __user *)(unsigned long)cmd.response,
1077                         &resp, sizeof(resp))) {
1078                ret = -EFAULT;
1079                goto err3;
1080        }
1081
1082        mutex_unlock(&file->mut);
1083        ucma_put_ctx(ctx);
1084        return 0;
1085
1086err3:
1087        rdma_leave_multicast(ctx->cm_id, (struct sockaddr *) &mc->addr);
1088        ucma_cleanup_mc_events(mc);
1089err2:
1090        mutex_lock(&mut);
1091        idr_remove(&multicast_idr, mc->id);
1092        mutex_unlock(&mut);
1093        list_del(&mc->list);
1094        kfree(mc);
1095err1:
1096        mutex_unlock(&file->mut);
1097        ucma_put_ctx(ctx);
1098        return ret;
1099}
1100
1101static ssize_t ucma_leave_multicast(struct ucma_file *file,
1102                                    const char __user *inbuf,
1103                                    int in_len, int out_len)
1104{
1105        struct rdma_ucm_destroy_id cmd;
1106        struct rdma_ucm_destroy_id_resp resp;
1107        struct ucma_multicast *mc;
1108        int ret = 0;
1109
1110        if (out_len < sizeof(resp))
1111                return -ENOSPC;
1112
1113        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
1114                return -EFAULT;
1115
1116        mutex_lock(&mut);
1117        mc = idr_find(&multicast_idr, cmd.id);
1118        if (!mc)
1119                mc = ERR_PTR(-ENOENT);
1120        else if (mc->ctx->file != file)
1121                mc = ERR_PTR(-EINVAL);
1122        else {
1123                idr_remove(&multicast_idr, mc->id);
1124                atomic_inc(&mc->ctx->ref);
1125        }
1126        mutex_unlock(&mut);
1127
1128        if (IS_ERR(mc)) {
1129                ret = PTR_ERR(mc);
1130                goto out;
1131        }
1132
1133        rdma_leave_multicast(mc->ctx->cm_id, (struct sockaddr *) &mc->addr);
1134        mutex_lock(&mc->ctx->file->mut);
1135        ucma_cleanup_mc_events(mc);
1136        list_del(&mc->list);
1137        mutex_unlock(&mc->ctx->file->mut);
1138
1139        ucma_put_ctx(mc->ctx);
1140        resp.events_reported = mc->events_reported;
1141        kfree(mc);
1142
1143        if (copy_to_user((void __user *)(unsigned long)cmd.response,
1144                         &resp, sizeof(resp)))
1145                ret = -EFAULT;
1146out:
1147        return ret;
1148}
1149
1150static void ucma_lock_files(struct ucma_file *file1, struct ucma_file *file2)
1151{
1152        /* Acquire mutex's based on pointer comparison to prevent deadlock. */
1153        if (file1 < file2) {
1154                mutex_lock(&file1->mut);
1155                mutex_lock(&file2->mut);
1156        } else {
1157                mutex_lock(&file2->mut);
1158                mutex_lock(&file1->mut);
1159        }
1160}
1161
1162static void ucma_unlock_files(struct ucma_file *file1, struct ucma_file *file2)
1163{
1164        if (file1 < file2) {
1165                mutex_unlock(&file2->mut);
1166                mutex_unlock(&file1->mut);
1167        } else {
1168                mutex_unlock(&file1->mut);
1169                mutex_unlock(&file2->mut);
1170        }
1171}
1172
1173static void ucma_move_events(struct ucma_context *ctx, struct ucma_file *file)
1174{
1175        struct ucma_event *uevent, *tmp;
1176
1177        list_for_each_entry_safe(uevent, tmp, &ctx->file->event_list, list)
1178                if (uevent->ctx == ctx)
1179                        list_move_tail(&uevent->list, &file->event_list);
1180}
1181
1182static ssize_t ucma_migrate_id(struct ucma_file *new_file,
1183                               const char __user *inbuf,
1184                               int in_len, int out_len)
1185{
1186        struct rdma_ucm_migrate_id cmd;
1187        struct rdma_ucm_migrate_resp resp;
1188        struct ucma_context *ctx;
1189        struct file *filp;
1190        struct ucma_file *cur_file;
1191        int ret = 0;
1192
1193        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
1194                return -EFAULT;
1195
1196        /* Get current fd to protect against it being closed */
1197        filp = fget(cmd.fd);
1198        if (!filp)
1199                return -ENOENT;
1200
1201        /* Validate current fd and prevent destruction of id. */
1202        ctx = ucma_get_ctx(filp->private_data, cmd.id);
1203        if (IS_ERR(ctx)) {
1204                ret = PTR_ERR(ctx);
1205                goto file_put;
1206        }
1207
1208        cur_file = ctx->file;
1209        if (cur_file == new_file) {
1210                resp.events_reported = ctx->events_reported;
1211                goto response;
1212        }
1213
1214        /*
1215         * Migrate events between fd's, maintaining order, and avoiding new
1216         * events being added before existing events.
1217         */
1218        ucma_lock_files(cur_file, new_file);
1219        mutex_lock(&mut);
1220
1221        list_move_tail(&ctx->list, &new_file->ctx_list);
1222        ucma_move_events(ctx, new_file);
1223        ctx->file = new_file;
1224        resp.events_reported = ctx->events_reported;
1225
1226        mutex_unlock(&mut);
1227        ucma_unlock_files(cur_file, new_file);
1228
1229response:
1230        if (copy_to_user((void __user *)(unsigned long)cmd.response,
1231                         &resp, sizeof(resp)))
1232                ret = -EFAULT;
1233
1234        ucma_put_ctx(ctx);
1235file_put:
1236        fput(filp);
1237        return ret;
1238}
1239
1240static ssize_t (*ucma_cmd_table[])(struct ucma_file *file,
1241                                   const char __user *inbuf,
1242                                   int in_len, int out_len) = {
1243        [RDMA_USER_CM_CMD_CREATE_ID]    = ucma_create_id,
1244        [RDMA_USER_CM_CMD_DESTROY_ID]   = ucma_destroy_id,
1245        [RDMA_USER_CM_CMD_BIND_ADDR]    = ucma_bind_addr,
1246        [RDMA_USER_CM_CMD_RESOLVE_ADDR] = ucma_resolve_addr,
1247        [RDMA_USER_CM_CMD_RESOLVE_ROUTE]= ucma_resolve_route,
1248        [RDMA_USER_CM_CMD_QUERY_ROUTE]  = ucma_query_route,
1249        [RDMA_USER_CM_CMD_CONNECT]      = ucma_connect,
1250        [RDMA_USER_CM_CMD_LISTEN]       = ucma_listen,
1251        [RDMA_USER_CM_CMD_ACCEPT]       = ucma_accept,
1252        [RDMA_USER_CM_CMD_REJECT]       = ucma_reject,
1253        [RDMA_USER_CM_CMD_DISCONNECT]   = ucma_disconnect,
1254        [RDMA_USER_CM_CMD_INIT_QP_ATTR] = ucma_init_qp_attr,
1255        [RDMA_USER_CM_CMD_GET_EVENT]    = ucma_get_event,
1256        [RDMA_USER_CM_CMD_GET_OPTION]   = NULL,
1257        [RDMA_USER_CM_CMD_SET_OPTION]   = ucma_set_option,
1258        [RDMA_USER_CM_CMD_NOTIFY]       = ucma_notify,
1259        [RDMA_USER_CM_CMD_JOIN_MCAST]   = ucma_join_multicast,
1260        [RDMA_USER_CM_CMD_LEAVE_MCAST]  = ucma_leave_multicast,
1261        [RDMA_USER_CM_CMD_MIGRATE_ID]   = ucma_migrate_id
1262};
1263
1264static ssize_t ucma_write(struct file *filp, const char __user *buf,
1265                          size_t len, loff_t *pos)
1266{
1267        struct ucma_file *file = filp->private_data;
1268        struct rdma_ucm_cmd_hdr hdr;
1269        ssize_t ret;
1270
1271        if (len < sizeof(hdr))
1272                return -EINVAL;
1273
1274        if (copy_from_user(&hdr, buf, sizeof(hdr)))
1275                return -EFAULT;
1276
1277        if (hdr.cmd >= ARRAY_SIZE(ucma_cmd_table))
1278                return -EINVAL;
1279
1280        if (hdr.in + sizeof(hdr) > len)
1281                return -EINVAL;
1282
1283        if (!ucma_cmd_table[hdr.cmd])
1284                return -ENOSYS;
1285
1286        ret = ucma_cmd_table[hdr.cmd](file, buf + sizeof(hdr), hdr.in, hdr.out);
1287        if (!ret)
1288                ret = len;
1289
1290        return ret;
1291}
1292
1293static unsigned int ucma_poll(struct file *filp, struct poll_table_struct *wait)
1294{
1295        struct ucma_file *file = filp->private_data;
1296        unsigned int mask = 0;
1297
1298        poll_wait(filp, &file->poll_wait, wait);
1299
1300        if (!list_empty(&file->event_list))
1301                mask = POLLIN | POLLRDNORM;
1302
1303        return mask;
1304}
1305
1306/*
1307 * ucma_open() does not need the BKL:
1308 *
1309 *  - no global state is referred to;
1310 *  - there is no ioctl method to race against;
1311 *  - no further module initialization is required for open to work
1312 *    after the device is registered.
1313 */
1314static int ucma_open(struct inode *inode, struct file *filp)
1315{
1316        struct ucma_file *file;
1317
1318        file = kmalloc(sizeof *file, GFP_KERNEL);
1319        if (!file)
1320                return -ENOMEM;
1321
1322        INIT_LIST_HEAD(&file->event_list);
1323        INIT_LIST_HEAD(&file->ctx_list);
1324        init_waitqueue_head(&file->poll_wait);
1325        mutex_init(&file->mut);
1326
1327        filp->private_data = file;
1328        file->filp = filp;
1329
1330        return nonseekable_open(inode, filp);
1331}
1332
1333static int ucma_close(struct inode *inode, struct file *filp)
1334{
1335        struct ucma_file *file = filp->private_data;
1336        struct ucma_context *ctx, *tmp;
1337
1338        mutex_lock(&file->mut);
1339        list_for_each_entry_safe(ctx, tmp, &file->ctx_list, list) {
1340                mutex_unlock(&file->mut);
1341
1342                mutex_lock(&mut);
1343                idr_remove(&ctx_idr, ctx->id);
1344                mutex_unlock(&mut);
1345
1346                ucma_free_ctx(ctx);
1347                mutex_lock(&file->mut);
1348        }
1349        mutex_unlock(&file->mut);
1350        kfree(file);
1351        return 0;
1352}
1353
1354static const struct file_operations ucma_fops = {
1355        .owner   = THIS_MODULE,
1356        .open    = ucma_open,
1357        .release = ucma_close,
1358        .write   = ucma_write,
1359        .poll    = ucma_poll,
1360        .llseek  = no_llseek,
1361};
1362
1363static struct miscdevice ucma_misc = {
1364        .minor          = MISC_DYNAMIC_MINOR,
1365        .name           = "rdma_cm",
1366        .nodename       = "infiniband/rdma_cm",
1367        .mode           = 0666,
1368        .fops           = &ucma_fops,
1369};
1370
1371static ssize_t show_abi_version(struct device *dev,
1372                                struct device_attribute *attr,
1373                                char *buf)
1374{
1375        return sprintf(buf, "%d\n", RDMA_USER_CM_ABI_VERSION);
1376}
1377static DEVICE_ATTR(abi_version, S_IRUGO, show_abi_version, NULL);
1378
1379static int __init ucma_init(void)
1380{
1381        int ret;
1382
1383        ret = misc_register(&ucma_misc);
1384        if (ret)
1385                return ret;
1386
1387        ret = device_create_file(ucma_misc.this_device, &dev_attr_abi_version);
1388        if (ret) {
1389                printk(KERN_ERR "rdma_ucm: couldn't create abi_version attr\n");
1390                goto err1;
1391        }
1392
1393        ucma_ctl_table_hdr = register_sysctl_paths(ucma_ctl_path, ucma_ctl_table);
1394        if (!ucma_ctl_table_hdr) {
1395                printk(KERN_ERR "rdma_ucm: couldn't register sysctl paths\n");
1396                ret = -ENOMEM;
1397                goto err2;
1398        }
1399        return 0;
1400err2:
1401        device_remove_file(ucma_misc.this_device, &dev_attr_abi_version);
1402err1:
1403        misc_deregister(&ucma_misc);
1404        return ret;
1405}
1406
1407static void __exit ucma_cleanup(void)
1408{
1409        unregister_sysctl_table(ucma_ctl_table_hdr);
1410        device_remove_file(ucma_misc.this_device, &dev_attr_abi_version);
1411        misc_deregister(&ucma_misc);
1412        idr_destroy(&ctx_idr);
1413}
1414
1415module_init(ucma_init);
1416module_exit(ucma_cleanup);
1417
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.