include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / drivers / infiniband / core / cma.c
index 699ad12..7794249 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/random.h>
 #include <linux/idr.h>
 #include <linux/inetdevice.h>
+#include <linux/slab.h>
 
 #include <net/tcp.h>
 #include <net/ipv6.h>
@@ -330,17 +331,7 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv)
        union ib_gid gid;
        int ret = -ENODEV;
 
-       switch (rdma_node_get_transport(dev_addr->dev_type)) {
-       case RDMA_TRANSPORT_IB:
-               ib_addr_get_sgid(dev_addr, &gid);
-               break;
-       case RDMA_TRANSPORT_IWARP:
-               iw_addr_get_sgid(dev_addr, &gid);
-               break;
-       default:
-               return -ENODEV;
-       }
-
+       rdma_addr_get_sgid(dev_addr, &gid);
        list_for_each_entry(cma_dev, &dev_list, list) {
                ret = ib_find_cached_gid(cma_dev->device, &gid,
                                         &id_priv->id.port_num, NULL);
@@ -1032,11 +1023,17 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
        if (rt->num_paths == 2)
                rt->path_rec[1] = *ib_event->param.req_rcvd.alternate_path;
 
-       ib_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid);
-       ret = rdma_translate_ip((struct sockaddr *) &id->route.addr.src_addr,
-                               &id->route.addr.dev_addr);
-       if (ret)
-               goto destroy_id;
+       if (cma_any_addr((struct sockaddr *) &rt->addr.src_addr)) {
+               rt->addr.dev_addr.dev_type = ARPHRD_INFINIBAND;
+               rdma_addr_set_sgid(&rt->addr.dev_addr, &rt->path_rec[0].sgid);
+               ib_addr_set_pkey(&rt->addr.dev_addr, rt->path_rec[0].pkey);
+       } else {
+               ret = rdma_translate_ip((struct sockaddr *) &rt->addr.src_addr,
+                                       &rt->addr.dev_addr);
+               if (ret)
+                       goto destroy_id;
+       }
+       rdma_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid);
 
        id_priv = container_of(id, struct rdma_id_private, id);
        id_priv->state = CMA_CONNECT;
@@ -1071,10 +1068,12 @@ static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id,
        cma_save_net_info(&id->route.addr, &listen_id->route.addr,
                          ip_ver, port, src, dst);
 
-       ret = rdma_translate_ip((struct sockaddr *) &id->route.addr.src_addr,
-                               &id->route.addr.dev_addr);
-       if (ret)
-               goto err;
+       if (!cma_any_addr((struct sockaddr *) &id->route.addr.src_addr)) {
+               ret = rdma_translate_ip((struct sockaddr *) &id->route.addr.src_addr,
+                                       &id->route.addr.dev_addr);
+               if (ret)
+                       goto err;
+       }
 
        id_priv = container_of(id, struct rdma_id_private, id);
        id_priv->state = CMA_CONNECT;
@@ -1474,15 +1473,6 @@ static void cma_listen_on_all(struct rdma_id_private *id_priv)
        mutex_unlock(&lock);
 }
 
-static int cma_bind_any(struct rdma_cm_id *id, sa_family_t af)
-{
-       struct sockaddr_storage addr_in;
-
-       memset(&addr_in, 0, sizeof addr_in);
-       addr_in.ss_family = af;
-       return rdma_bind_addr(id, (struct sockaddr *) &addr_in);
-}
-
 int rdma_listen(struct rdma_cm_id *id, int backlog)
 {
        struct rdma_id_private *id_priv;
@@ -1490,7 +1480,8 @@ int rdma_listen(struct rdma_cm_id *id, int backlog)
 
        id_priv = container_of(id, struct rdma_id_private, id);
        if (id_priv->state == CMA_IDLE) {
-               ret = cma_bind_any(id, AF_INET);
+               ((struct sockaddr *) &id->route.addr.src_addr)->sa_family = AF_INET;
+               ret = rdma_bind_addr(id, (struct sockaddr *) &id->route.addr.src_addr);
                if (ret)
                        return ret;
        }
@@ -1565,8 +1556,8 @@ static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms,
        struct sockaddr_in6 *sin6;
 
        memset(&path_rec, 0, sizeof path_rec);
-       ib_addr_get_sgid(&addr->dev_addr, &path_rec.sgid);
-       ib_addr_get_dgid(&addr->dev_addr, &path_rec.dgid);
+       rdma_addr_get_sgid(&addr->dev_addr, &path_rec.sgid);
+       rdma_addr_get_dgid(&addr->dev_addr, &path_rec.dgid);
        path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(&addr->dev_addr));
        path_rec.numb_path = 1;
        path_rec.reversible = 1;
@@ -1781,7 +1772,11 @@ port_found:
        if (ret)
                goto out;
 
-       ib_addr_set_sgid(&id_priv->id.route.addr.dev_addr, &gid);
+       id_priv->id.route.addr.dev_addr.dev_type =
+               (rdma_node_get_transport(cma_dev->device->node_type) == RDMA_TRANSPORT_IB) ?
+               ARPHRD_INFINIBAND : ARPHRD_ETHER;
+
+       rdma_addr_set_sgid(&id_priv->id.route.addr.dev_addr, &gid);
        ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey);
        id_priv->id.port_num = p;
        cma_attach_to_dev(id_priv, cma_dev);
@@ -1839,7 +1834,7 @@ out:
 static int cma_resolve_loopback(struct rdma_id_private *id_priv)
 {
        struct cma_work *work;
-       struct sockaddr_in *src_in, *dst_in;
+       struct sockaddr *src, *dst;
        union ib_gid gid;
        int ret;
 
@@ -1853,14 +1848,19 @@ static int cma_resolve_loopback(struct rdma_id_private *id_priv)
                        goto err;
        }
 
-       ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid);
-       ib_addr_set_dgid(&id_priv->id.route.addr.dev_addr, &gid);
+       rdma_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid);
+       rdma_addr_set_dgid(&id_priv->id.route.addr.dev_addr, &gid);
 
-       if (cma_zero_addr((struct sockaddr *) &id_priv->id.route.addr.src_addr)) {
-               src_in = (struct sockaddr_in *)&id_priv->id.route.addr.src_addr;
-               dst_in = (struct sockaddr_in *)&id_priv->id.route.addr.dst_addr;
-               src_in->sin_family = dst_in->sin_family;
-               src_in->sin_addr.s_addr = dst_in->sin_addr.s_addr;
+       src = (struct sockaddr *) &id_priv->id.route.addr.src_addr;
+       if (cma_zero_addr(src)) {
+               dst = (struct sockaddr *) &id_priv->id.route.addr.dst_addr;
+               if ((src->sa_family = dst->sa_family) == AF_INET) {
+                       ((struct sockaddr_in *) src)->sin_addr.s_addr =
+                               ((struct sockaddr_in *) dst)->sin_addr.s_addr;
+               } else {
+                       ipv6_addr_copy(&((struct sockaddr_in6 *) src)->sin6_addr,
+                                      &((struct sockaddr_in6 *) dst)->sin6_addr);
+               }
        }
 
        work->id = id_priv;
@@ -1878,10 +1878,14 @@ err:
 static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
                         struct sockaddr *dst_addr)
 {
-       if (src_addr && src_addr->sa_family)
-               return rdma_bind_addr(id, src_addr);
-       else
-               return cma_bind_any(id, dst_addr->sa_family);
+       if (!src_addr || !src_addr->sa_family) {
+               src_addr = (struct sockaddr *) &id->route.addr.src_addr;
+               if ((src_addr->sa_family = dst_addr->sa_family) == AF_INET6) {
+                       ((struct sockaddr_in6 *) src_addr)->sin6_scope_id =
+                               ((struct sockaddr_in6 *) dst_addr)->sin6_scope_id;
+               }
+       }
+       return rdma_bind_addr(id, src_addr);
 }
 
 int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
@@ -2077,6 +2081,25 @@ static int cma_get_port(struct rdma_id_private *id_priv)
        return ret;
 }
 
+static int cma_check_linklocal(struct rdma_dev_addr *dev_addr,
+                              struct sockaddr *addr)
+{
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+       struct sockaddr_in6 *sin6;
+
+       if (addr->sa_family != AF_INET6)
+               return 0;
+
+       sin6 = (struct sockaddr_in6 *) addr;
+       if ((ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) &&
+           !sin6->sin6_scope_id)
+                       return -EINVAL;
+
+       dev_addr->bound_dev_if = sin6->sin6_scope_id;
+#endif
+       return 0;
+}
+
 int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
 {
        struct rdma_id_private *id_priv;
@@ -2089,6 +2112,10 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
        if (!cma_comp_exch(id_priv, CMA_IDLE, CMA_ADDR_BOUND))
                return -EINVAL;
 
+       ret = cma_check_linklocal(&id->route.addr.dev_addr, addr);
+       if (ret)
+               goto err1;
+
        if (!cma_any_addr(addr)) {
                ret = rdma_translate_ip(addr, &id->route.addr.dev_addr);
                if (ret)
@@ -2108,7 +2135,7 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
 
        return 0;
 err2:
-       if (!cma_any_addr(addr)) {
+       if (id_priv->cma_dev) {
                mutex_lock(&lock);
                cma_detach_from_dev(id_priv);
                mutex_unlock(&lock);
@@ -2721,7 +2748,7 @@ static int cma_join_ib_multicast(struct rdma_id_private *id_priv,
        cma_set_mgid(id_priv, (struct sockaddr *) &mc->addr, &rec.mgid);
        if (id_priv->id.ps == RDMA_PS_UDP)
                rec.qkey = cpu_to_be32(RDMA_UDP_QKEY);
-       ib_addr_get_sgid(dev_addr, &rec.port_gid);
+       rdma_addr_get_sgid(dev_addr, &rec.port_gid);
        rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr));
        rec.join_state = 1;