OSDN Git Service

IB/cm: Keep track of the sgid_attr that created the cm id
authorParav Pandit <parav@mellanox.com>
Tue, 19 Jun 2018 07:59:17 +0000 (10:59 +0300)
committerJason Gunthorpe <jgg@mellanox.com>
Mon, 25 Jun 2018 20:19:56 +0000 (14:19 -0600)
Hold reference to the the sgid_attr which is used in a cm_id until the
cm_id is destroyed.

Signed-off-by: Parav Pandit <parav@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
drivers/infiniband/core/cma.c
include/rdma/ib_addr.h

index 367aa75..de7d250 100644 (file)
@@ -603,46 +603,54 @@ static int cma_translate_addr(struct sockaddr *addr, struct rdma_dev_addr *dev_a
        return ret;
 }
 
-static inline int cma_validate_port(struct ib_device *device, u8 port,
-                                   enum ib_gid_type gid_type,
-                                   union ib_gid *gid,
-                                   struct rdma_id_private *id_priv)
+static const struct ib_gid_attr *
+cma_validate_port(struct ib_device *device, u8 port,
+                 enum ib_gid_type gid_type,
+                 union ib_gid *gid,
+                 struct rdma_id_private *id_priv)
 {
        struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
        int bound_if_index = dev_addr->bound_dev_if;
+       const struct ib_gid_attr *sgid_attr;
        int dev_type = dev_addr->dev_type;
        struct net_device *ndev = NULL;
-       int ret = -ENODEV;
 
        if ((dev_type == ARPHRD_INFINIBAND) && !rdma_protocol_ib(device, port))
-               return ret;
+               return ERR_PTR(-ENODEV);
 
        if ((dev_type != ARPHRD_INFINIBAND) && rdma_protocol_ib(device, port))
-               return ret;
+               return ERR_PTR(-ENODEV);
 
        if (dev_type == ARPHRD_ETHER && rdma_protocol_roce(device, port)) {
                ndev = dev_get_by_index(dev_addr->net, bound_if_index);
                if (!ndev)
-                       return ret;
+                       return ERR_PTR(-ENODEV);
        } else {
                gid_type = IB_GID_TYPE_IB;
        }
 
-       ret = ib_find_cached_gid_by_port(device, gid, gid_type, port,
-                                        ndev, NULL);
-
+       sgid_attr = rdma_find_gid_by_port(device, gid, gid_type, port, ndev);
        if (ndev)
                dev_put(ndev);
+       return sgid_attr;
+}
 
-       return ret;
+static void cma_bind_sgid_attr(struct rdma_id_private *id_priv,
+                              const struct ib_gid_attr *sgid_attr)
+{
+       WARN_ON(id_priv->id.route.addr.dev_addr.sgid_attr);
+       id_priv->id.route.addr.dev_addr.sgid_attr = sgid_attr;
 }
 
 static int cma_acquire_dev(struct rdma_id_private *id_priv,
                           struct rdma_id_private *listen_id_priv)
 {
        struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
+       const struct ib_gid_attr *sgid_attr;
        struct cma_device *cma_dev;
        union ib_gid gid, iboe_gid, *gidp;
+       enum ib_gid_type gid_type;
+       enum ib_gid_type default_type;
        int ret = -ENODEV;
        u8 port;
 
@@ -662,14 +670,15 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv,
                port = listen_id_priv->id.port_num;
                gidp = rdma_protocol_roce(cma_dev->device, port) ?
                       &iboe_gid : &gid;
-
-               ret = cma_validate_port(cma_dev->device, port,
-                                       rdma_protocol_ib(cma_dev->device, port) ?
-                                       IB_GID_TYPE_IB :
-                                       listen_id_priv->gid_type, gidp,
-                                       id_priv);
-               if (!ret) {
+               gid_type = rdma_protocol_ib(cma_dev->device, port) ?
+                                           IB_GID_TYPE_IB :
+                                           listen_id_priv->gid_type;
+               sgid_attr = cma_validate_port(cma_dev->device, port,
+                                             gid_type, gidp, id_priv);
+               if (!IS_ERR(sgid_attr)) {
                        id_priv->id.port_num = port;
+                       cma_bind_sgid_attr(id_priv, sgid_attr);
+                       ret = 0;
                        goto out;
                }
        }
@@ -683,14 +692,16 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv,
 
                        gidp = rdma_protocol_roce(cma_dev->device, port) ?
                               &iboe_gid : &gid;
-
-                       ret = cma_validate_port(cma_dev->device, port,
-                                               rdma_protocol_ib(cma_dev->device, port) ?
-                                               IB_GID_TYPE_IB :
-                                               cma_dev->default_gid_type[port - 1],
-                                               gidp, id_priv);
-                       if (!ret) {
+                       default_type = cma_dev->default_gid_type[port - 1];
+                       gid_type =
+                               rdma_protocol_ib(cma_dev->device, port) ?
+                                                IB_GID_TYPE_IB : default_type;
+                       sgid_attr = cma_validate_port(cma_dev->device, port,
+                                                     gid_type, gidp, id_priv);
+                       if (!IS_ERR(sgid_attr)) {
                                id_priv->id.port_num = port;
+                               cma_bind_sgid_attr(id_priv, sgid_attr);
+                               ret = 0;
                                goto out;
                        }
                }
@@ -1706,6 +1717,10 @@ void rdma_destroy_id(struct rdma_cm_id *id)
                cma_deref_id(id_priv->id.context);
 
        kfree(id_priv->id.route.path_rec);
+
+       if (id_priv->id.route.addr.dev_addr.sgid_attr)
+               rdma_put_gid_attr(id_priv->id.route.addr.dev_addr.sgid_attr);
+
        put_net(id_priv->id.route.addr.dev_addr.net);
        kfree(id_priv);
 }
index c2c8b1f..715394f 100644 (file)
@@ -58,6 +58,7 @@
  * @bound_dev_if:      An optional device interface index.
  * @transport:         The transport type used.
  * @net:               Network namespace containing the bound_dev_if net_dev.
+ * @sgid_attr:         GID attribute to use for identified SGID
  */
 struct rdma_dev_addr {
        unsigned char src_dev_addr[MAX_ADDR_LEN];
@@ -67,6 +68,7 @@ struct rdma_dev_addr {
        int bound_dev_if;
        enum rdma_transport_type transport;
        struct net *net;
+       const struct ib_gid_attr *sgid_attr;
        enum rdma_network_type network;
        int hoplimit;
 };