>It would be nice to avoid adding another workqueue.

Here's an updated patch that exports the work queue in ib_addr and has the CMA
make use of that one.

Thanks for the feedback - please respond if there are any other issues.

Signed-off-by: Sean Hefty <[EMAIL PROTECTED]>


Index: include/rdma/ib_addr.h
===================================================================
--- include/rdma/ib_addr.h      (revision 4651)
+++ include/rdma/ib_addr.h      (working copy)
@@ -30,9 +30,13 @@
 #if !defined(IB_ADDR_H)
 #define IB_ADDR_H
 
+#include <linux/in.h>
+#include <linux/in6.h>
 #include <linux/socket.h>
 #include <rdma/ib_verbs.h>
 
+extern struct workqueue_struct *rdma_wq;
+
 struct ib_addr {
        union ib_gid    sgid;
        union ib_gid    dgid;
@@ -68,5 +72,11 @@
 
 void ib_addr_cancel(struct ib_addr *addr);
 
+static inline int ip_addr_size(struct sockaddr *addr)
+{
+       return addr->sa_family == AF_INET6 ?
+              sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
+}
+
 #endif /* IB_ADDR_H */
 
Index: core/addr.c
===================================================================
--- core/addr.c (revision 4651)
+++ core/addr.c (working copy)
@@ -27,8 +27,6 @@
  * notice, one of the license notices in the documentation
  * and/or other materials provided with the distribution.
  */
-#include <linux/in.h>
-#include <linux/in6.h>
 #include <linux/inetdevice.h>
 #include <linux/workqueue.h>
 #include <net/arp.h>
@@ -57,7 +55,8 @@
 static DECLARE_MUTEX(mutex);
 static LIST_HEAD(req_list);
 static DECLARE_WORK(work, process_req, NULL);
-static struct workqueue_struct *wq;
+struct workqueue_struct *rdma_wq;
+EXPORT_SYMBOL(rdma_wq);
 
 static u16 addr_get_pkey(struct net_device *dev)
 {
@@ -90,7 +89,7 @@
        if ((long)delay <= 0)
                delay = 1;
 
-       queue_delayed_work(wq, &work, delay);
+       queue_delayed_work(rdma_wq, &work, delay);
 }
 
 static void queue_req(struct addr_req *req)
@@ -258,8 +257,8 @@
        memset(req, 0, sizeof *req);
 
        if (src_addr)
-               req->src_addr = *src_addr;
-       req->dst_addr = *dst_addr;
+               memcpy(&req->src_addr, src_addr, ip_addr_size(src_addr));
+       memcpy(&req->dst_addr, dst_addr, ip_addr_size(dst_addr));
        req->addr = addr;
        req->callback = callback;
        req->context = context;
@@ -333,8 +332,8 @@
 
 static int addr_init(void)
 {
-       wq = create_singlethread_workqueue("ib_addr");
-       if (!wq)
+       rdma_wq = create_singlethread_workqueue("rdma_wq");
+       if (!rdma_wq)
                return -ENOMEM;
 
        dev_add_pack(&addr_arp);
@@ -344,7 +343,7 @@
 static void addr_cleanup(void)
 {
        dev_remove_pack(&addr_arp);
-       destroy_workqueue(wq);
+       destroy_workqueue(rdma_wq);
 }
 
 module_init(addr_init);
Index: core/cma.c
===================================================================
--- core/cma.c  (revision 4651)
+++ core/cma.c  (working copy)
@@ -421,6 +421,12 @@
        }
 }
 
+static inline int cma_loopback_addr(struct sockaddr *addr)
+{
+       return ((struct sockaddr_in *) addr)->sin_addr.s_addr ==
+               ntohl(INADDR_LOOPBACK);
+}
+
 static int cma_get_net_info(void *hdr, enum rdma_port_space ps,
                            u8 *ip_ver, __u16 *port,
                            union cma_ip_addr **src, union cma_ip_addr **dst)
@@ -1070,6 +1076,35 @@
 }
 EXPORT_SYMBOL(rdma_resolve_route);
 
+static int cma_bind_loopback(struct rdma_id_private *id_priv)
+{
+       struct cma_device *cma_dev;
+       int ret;
+
+       down(&mutex);
+       if (list_empty(&dev_list)) {
+               ret = -ENODEV;
+               goto out;
+       }
+
+       cma_dev = list_entry(dev_list.next, struct cma_device, list);
+       ret = ib_get_cached_gid(cma_dev->device, 1, 0,
+                               &id_priv->id.route.addr.addr.ibaddr.sgid);
+       if (ret)
+               goto out;
+
+       ret = ib_get_cached_pkey(cma_dev->device, 1, 0,
+                                &id_priv->id.route.addr.addr.ibaddr.pkey);
+       if (ret)
+               goto out;
+
+       id_priv->id.port_num = 1;
+       cma_attach_to_dev(id_priv, cma_dev);
+out:
+       up(&mutex);
+       return ret;
+}
+
 static void addr_handler(int status, struct sockaddr *src_addr,
                         struct ib_addr *ibaddr, void *context)
 {
@@ -1092,7 +1127,8 @@
        } else {
                if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_RESOLVED))
                        goto out;
-               id_priv->id.route.addr.src_addr = *src_addr;
+               memcpy(&id_priv->id.route.addr.src_addr, src_addr,
+                      ip_addr_size(src_addr));
                event = RDMA_CM_EVENT_ADDR_RESOLVED;
        }
 
@@ -1108,6 +1144,57 @@
        cma_deref_id(id_priv);
 }
 
+static void loopback_addr_handler(void *data)
+{
+       struct rdma_id_private *id_priv = data;
+
+       atomic_inc(&id_priv->dev_remove);
+
+       if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_RESOLVED))
+               goto out;
+
+       if (cma_notify_user(id_priv, RDMA_CM_EVENT_ADDR_RESOLVED, 0, NULL, 0)) {
+               cma_exch(id_priv, CMA_DESTROYING);
+               cma_release_remove(id_priv);
+               cma_deref_id(id_priv);
+               rdma_destroy_id(&id_priv->id);
+               return;
+       }
+out:
+       cma_release_remove(id_priv);
+       cma_deref_id(id_priv);
+}
+
+static int cma_resolve_loopback(struct rdma_id_private *id_priv,
+                               struct sockaddr *src_addr, enum cma_state state)
+{
+       struct work_struct *work;
+       int ret;
+
+       work = kmalloc(sizeof *work, GFP_KERNEL);
+       if (!work)
+               return -ENOMEM;
+
+       if (state == CMA_IDLE) {
+               ret = cma_bind_loopback(id_priv);
+               if (ret)
+                       goto err;
+               id_priv->id.route.addr.addr.ibaddr.dgid =
+                               id_priv->id.route.addr.addr.ibaddr.sgid;
+               if (!src_addr || cma_any_addr(src_addr))
+                       src_addr = &id_priv->id.route.addr.dst_addr;
+               memcpy(&id_priv->id.route.addr.src_addr, src_addr,
+                      ip_addr_size(src_addr));
+       }
+
+       INIT_WORK(work, loopback_addr_handler, id_priv);
+       queue_work(rdma_wq, work);
+       return 0;
+err:
+       kfree(work);
+       return ret;
+}
+
 int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
                      struct sockaddr *dst_addr, int timeout_ms)
 {
@@ -1126,9 +1213,13 @@
                return -EINVAL;
 
        atomic_inc(&id_priv->refcount);
-       id->route.addr.dst_addr = *dst_addr;
-       ret = ib_resolve_addr(src_addr, dst_addr, &id->route.addr.addr.ibaddr,
-                             timeout_ms, addr_handler, id_priv);
+       memcpy(&id->route.addr.dst_addr, dst_addr, ip_addr_size(dst_addr));
+       if (cma_loopback_addr(dst_addr))
+               ret = cma_resolve_loopback(id_priv, src_addr, expected_state);
+       else
+               ret = ib_resolve_addr(src_addr, dst_addr,
+                                     &id->route.addr.addr.ibaddr,
+                                     timeout_ms, addr_handler, id_priv);
        if (ret)
                goto err;
 
@@ -1143,7 +1234,7 @@
 int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
 {
        struct rdma_id_private *id_priv;
-       struct ib_addr *ibaddr = &id->route.addr.addr.ibaddr;
+       struct ib_addr *ibaddr;
        int ret;
 
        if (addr->sa_family != AF_INET)
@@ -1154,9 +1245,11 @@
                return -EINVAL;
 
        if (cma_any_addr(addr)) {
-               id->route.addr.src_addr = *addr;
                ret = 0;
+       } else if (cma_loopback_addr(addr)) {
+               ret = cma_bind_loopback(id_priv);
        } else {
+               ibaddr = &id->route.addr.addr.ibaddr;
                ret = ib_translate_addr(addr, &ibaddr->sgid, &ibaddr->pkey);
                if (!ret)
                        ret = cma_acquire_ib_dev(id_priv, &ibaddr->sgid);
@@ -1165,7 +1258,7 @@
        if (ret)
                goto err;
 
-       id->route.addr.src_addr = *addr;
+       memcpy(&id->route.addr.src_addr, addr, ip_addr_size(addr));
        return 0;
 err:
        cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_IDLE);



_______________________________________________
openib-general mailing list
[email protected]
http://openib.org/mailman/listinfo/openib-general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to