include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / drivers / infiniband / core / ucma.c
index 15937eb..4618508 100644 (file)
 #include <linux/file.h>
 #include <linux/mutex.h>
 #include <linux/poll.h>
+#include <linux/sched.h>
 #include <linux/idr.h>
 #include <linux/in.h>
 #include <linux/in6.h>
 #include <linux/miscdevice.h>
+#include <linux/slab.h>
 
 #include <rdma/rdma_user_cm.h>
 #include <rdma/ib_marshall.h>
 #include <rdma/rdma_cm.h>
+#include <rdma/rdma_cm_ib.h>
 
 MODULE_AUTHOR("Sean Hefty");
 MODULE_DESCRIPTION("RDMA Userspace Connection Manager Access");
@@ -81,9 +84,7 @@ struct ucma_multicast {
 
        u64                     uid;
        struct list_head        list;
-       struct sockaddr         addr;
-       u8                      pad[sizeof(struct sockaddr_in6) -
-                                   sizeof(struct sockaddr)];
+       struct sockaddr_storage addr;
 };
 
 struct ucma_event {
@@ -563,10 +564,10 @@ static void ucma_copy_ib_route(struct rdma_ucm_query_route_resp *resp,
        switch (route->num_paths) {
        case 0:
                dev_addr = &route->addr.dev_addr;
-               ib_addr_get_dgid(dev_addr,
-                                (union ib_gid *) &resp->ib_route[0].dgid);
-               ib_addr_get_sgid(dev_addr,
-                                (union ib_gid *) &resp->ib_route[0].sgid);
+               rdma_addr_get_dgid(dev_addr,
+                                  (union ib_gid *) &resp->ib_route[0].dgid);
+               rdma_addr_get_sgid(dev_addr,
+                                  (union ib_gid *) &resp->ib_route[0].sgid);
                resp->ib_route[0].pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr));
                break;
        case 2:
@@ -603,18 +604,18 @@ static ssize_t ucma_query_route(struct ucma_file *file,
                return PTR_ERR(ctx);
 
        memset(&resp, 0, sizeof resp);
-       addr = &ctx->cm_id->route.addr.src_addr;
+       addr = (struct sockaddr *) &ctx->cm_id->route.addr.src_addr;
        memcpy(&resp.src_addr, addr, addr->sa_family == AF_INET ?
                                     sizeof(struct sockaddr_in) :
                                     sizeof(struct sockaddr_in6));
-       addr = &ctx->cm_id->route.addr.dst_addr;
+       addr = (struct sockaddr *) &ctx->cm_id->route.addr.dst_addr;
        memcpy(&resp.dst_addr, addr, addr->sa_family == AF_INET ?
                                     sizeof(struct sockaddr_in) :
                                     sizeof(struct sockaddr_in6));
        if (!ctx->cm_id->device)
                goto out;
 
-       resp.node_guid = ctx->cm_id->device->node_guid;
+       resp.node_guid = (__force __u64) ctx->cm_id->device->node_guid;
        resp.port_num = ctx->cm_id->port_num;
        switch (rdma_node_get_transport(ctx->cm_id->device->node_type)) {
        case RDMA_TRANSPORT_IB:
@@ -813,6 +814,51 @@ static int ucma_set_option_id(struct ucma_context *ctx, int optname,
        return ret;
 }
 
+static int ucma_set_ib_path(struct ucma_context *ctx,
+                           struct ib_path_rec_data *path_data, size_t optlen)
+{
+       struct ib_sa_path_rec sa_path;
+       struct rdma_cm_event event;
+       int ret;
+
+       if (optlen % sizeof(*path_data))
+               return -EINVAL;
+
+       for (; optlen; optlen -= sizeof(*path_data), path_data++) {
+               if (path_data->flags == (IB_PATH_GMP | IB_PATH_PRIMARY |
+                                        IB_PATH_BIDIRECTIONAL))
+                       break;
+       }
+
+       if (!optlen)
+               return -EINVAL;
+
+       ib_sa_unpack_path(path_data->path_rec, &sa_path);
+       ret = rdma_set_ib_paths(ctx->cm_id, &sa_path, 1);
+       if (ret)
+               return ret;
+
+       memset(&event, 0, sizeof event);
+       event.event = RDMA_CM_EVENT_ROUTE_RESOLVED;
+       return ucma_event_handler(ctx->cm_id, &event);
+}
+
+static int ucma_set_option_ib(struct ucma_context *ctx, int optname,
+                             void *optval, size_t optlen)
+{
+       int ret;
+
+       switch (optname) {
+       case RDMA_OPTION_IB_PATH:
+               ret = ucma_set_ib_path(ctx, optval, optlen);
+               break;
+       default:
+               ret = -ENOSYS;
+       }
+
+       return ret;
+}
+
 static int ucma_set_option_level(struct ucma_context *ctx, int level,
                                 int optname, void *optval, size_t optlen)
 {
@@ -822,6 +868,9 @@ static int ucma_set_option_level(struct ucma_context *ctx, int level,
        case RDMA_OPTION_ID:
                ret = ucma_set_option_id(ctx, optname, optval, optlen);
                break;
+       case RDMA_OPTION_IB:
+               ret = ucma_set_option_ib(ctx, optname, optval, optlen);
+               break;
        default:
                ret = -ENOSYS;
        }
@@ -906,14 +955,14 @@ static ssize_t ucma_join_multicast(struct ucma_file *file,
 
        mutex_lock(&file->mut);
        mc = ucma_alloc_multicast(ctx);
-       if (IS_ERR(mc)) {
-               ret = PTR_ERR(mc);
+       if (!mc) {
+               ret = -ENOMEM;
                goto err1;
        }
 
        mc->uid = cmd.uid;
        memcpy(&mc->addr, &cmd.addr, sizeof cmd.addr);
-       ret = rdma_join_multicast(ctx->cm_id, &mc->addr, mc);
+       ret = rdma_join_multicast(ctx->cm_id, (struct sockaddr *) &mc->addr, mc);
        if (ret)
                goto err2;
 
@@ -929,7 +978,7 @@ static ssize_t ucma_join_multicast(struct ucma_file *file,
        return 0;
 
 err3:
-       rdma_leave_multicast(ctx->cm_id, &mc->addr);
+       rdma_leave_multicast(ctx->cm_id, (struct sockaddr *) &mc->addr);
        ucma_cleanup_mc_events(mc);
 err2:
        mutex_lock(&mut);
@@ -975,7 +1024,7 @@ static ssize_t ucma_leave_multicast(struct ucma_file *file,
                goto out;
        }
 
-       rdma_leave_multicast(mc->ctx->cm_id, &mc->addr);
+       rdma_leave_multicast(mc->ctx->cm_id, (struct sockaddr *) &mc->addr);
        mutex_lock(&mc->ctx->file->mut);
        ucma_cleanup_mc_events(mc);
        list_del(&mc->list);
@@ -1148,6 +1197,14 @@ static unsigned int ucma_poll(struct file *filp, struct poll_table_struct *wait)
        return mask;
 }
 
+/*
+ * ucma_open() does not need the BKL:
+ *
+ *  - no global state is referred to;
+ *  - there is no ioctl method to race against;
+ *  - no further module initialization is required for open to work
+ *    after the device is registered.
+ */
 static int ucma_open(struct inode *inode, struct file *filp)
 {
        struct ucma_file *file;