|
@@ -438,6 +438,61 @@ out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Select the source IB device and address to reach the destination IB address.
|
|
|
+ */
|
|
|
+static int cma_resolve_ib_dev(struct rdma_id_private *id_priv)
|
|
|
+{
|
|
|
+ struct cma_device *cma_dev, *cur_dev;
|
|
|
+ struct sockaddr_ib *addr;
|
|
|
+ union ib_gid gid, sgid, *dgid;
|
|
|
+ u16 pkey, index;
|
|
|
+ u8 port, p;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ cma_dev = NULL;
|
|
|
+ addr = (struct sockaddr_ib *) cma_dst_addr(id_priv);
|
|
|
+ dgid = (union ib_gid *) &addr->sib_addr;
|
|
|
+ pkey = ntohs(addr->sib_pkey);
|
|
|
+
|
|
|
+ list_for_each_entry(cur_dev, &dev_list, list) {
|
|
|
+ if (rdma_node_get_transport(cur_dev->device->node_type) != RDMA_TRANSPORT_IB)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ for (p = 1; p <= cur_dev->device->phys_port_cnt; ++p) {
|
|
|
+ if (ib_find_cached_pkey(cur_dev->device, p, pkey, &index))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ for (i = 0; !ib_get_cached_gid(cur_dev->device, p, i, &gid); i++) {
|
|
|
+ if (!memcmp(&gid, dgid, sizeof(gid))) {
|
|
|
+ cma_dev = cur_dev;
|
|
|
+ sgid = gid;
|
|
|
+ port = p;
|
|
|
+ goto found;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!cma_dev && (gid.global.subnet_prefix ==
|
|
|
+ dgid->global.subnet_prefix)) {
|
|
|
+ cma_dev = cur_dev;
|
|
|
+ sgid = gid;
|
|
|
+ port = p;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!cma_dev)
|
|
|
+ return -ENODEV;
|
|
|
+
|
|
|
+found:
|
|
|
+ cma_attach_to_dev(id_priv, cma_dev);
|
|
|
+ id_priv->id.port_num = port;
|
|
|
+ addr = (struct sockaddr_ib *) cma_src_addr(id_priv);
|
|
|
+ memcpy(&addr->sib_addr, &sgid, sizeof sgid);
|
|
|
+ cma_translate_ib(addr, &id_priv->id.route.addr.dev_addr);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static void cma_deref_id(struct rdma_id_private *id_priv)
|
|
|
{
|
|
|
if (atomic_dec_and_test(&id_priv->refcount))
|
|
@@ -2101,14 +2156,48 @@ err:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static int cma_resolve_ib_addr(struct rdma_id_private *id_priv)
|
|
|
+{
|
|
|
+ struct cma_work *work;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ work = kzalloc(sizeof *work, GFP_KERNEL);
|
|
|
+ if (!work)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ if (!id_priv->cma_dev) {
|
|
|
+ ret = cma_resolve_ib_dev(id_priv);
|
|
|
+ if (ret)
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ rdma_addr_set_dgid(&id_priv->id.route.addr.dev_addr, (union ib_gid *)
|
|
|
+ &(((struct sockaddr_ib *) &id_priv->id.route.addr.dst_addr)->sib_addr));
|
|
|
+
|
|
|
+ work->id = id_priv;
|
|
|
+ INIT_WORK(&work->work, cma_work_handler);
|
|
|
+ work->old_state = RDMA_CM_ADDR_QUERY;
|
|
|
+ work->new_state = RDMA_CM_ADDR_RESOLVED;
|
|
|
+ work->event.event = RDMA_CM_EVENT_ADDR_RESOLVED;
|
|
|
+ queue_work(cma_wq, &work->work);
|
|
|
+ return 0;
|
|
|
+err:
|
|
|
+ kfree(work);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
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) {
|
|
|
src_addr = (struct sockaddr *) &id->route.addr.src_addr;
|
|
|
- if ((src_addr->sa_family = dst_addr->sa_family) == AF_INET6) {
|
|
|
+ src_addr->sa_family = dst_addr->sa_family;
|
|
|
+ if (dst_addr->sa_family == AF_INET6) {
|
|
|
((struct sockaddr_in6 *) src_addr)->sin6_scope_id =
|
|
|
((struct sockaddr_in6 *) dst_addr)->sin6_scope_id;
|
|
|
+ } else if (dst_addr->sa_family == AF_IB) {
|
|
|
+ ((struct sockaddr_ib *) src_addr)->sib_pkey =
|
|
|
+ ((struct sockaddr_ib *) dst_addr)->sib_pkey;
|
|
|
}
|
|
|
}
|
|
|
return rdma_bind_addr(id, src_addr);
|
|
@@ -2135,12 +2224,17 @@ int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
|
|
|
|
|
|
atomic_inc(&id_priv->refcount);
|
|
|
memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr));
|
|
|
- if (cma_any_addr(dst_addr))
|
|
|
+ if (cma_any_addr(dst_addr)) {
|
|
|
ret = cma_resolve_loopback(id_priv);
|
|
|
- else
|
|
|
- ret = rdma_resolve_ip(&addr_client, cma_src_addr(id_priv),
|
|
|
- dst_addr, &id->route.addr.dev_addr,
|
|
|
- timeout_ms, addr_handler, id_priv);
|
|
|
+ } else {
|
|
|
+ if (dst_addr->sa_family == AF_IB) {
|
|
|
+ ret = cma_resolve_ib_addr(id_priv);
|
|
|
+ } else {
|
|
|
+ ret = rdma_resolve_ip(&addr_client, cma_src_addr(id_priv),
|
|
|
+ dst_addr, &id->route.addr.dev_addr,
|
|
|
+ timeout_ms, addr_handler, id_priv);
|
|
|
+ }
|
|
|
+ }
|
|
|
if (ret)
|
|
|
goto err;
|
|
|
|