Commit 4ed13a5f authored by Parav Pandit's avatar Parav Pandit Committed by Jason Gunthorpe

IB/cm: Keep track of the sgid_attr that created the cm id

Hold reference to the the sgid_attr which is used in a cm_id until the
cm_id is destroyed.
Signed-off-by: default avatarParav Pandit <parav@mellanox.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
parent aa74f487
...@@ -603,46 +603,54 @@ static int cma_translate_addr(struct sockaddr *addr, struct rdma_dev_addr *dev_a ...@@ -603,46 +603,54 @@ static int cma_translate_addr(struct sockaddr *addr, struct rdma_dev_addr *dev_a
return ret; return ret;
} }
static inline int cma_validate_port(struct ib_device *device, u8 port, static const struct ib_gid_attr *
enum ib_gid_type gid_type, cma_validate_port(struct ib_device *device, u8 port,
union ib_gid *gid, enum ib_gid_type gid_type,
struct rdma_id_private *id_priv) union ib_gid *gid,
struct rdma_id_private *id_priv)
{ {
struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr; struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
int bound_if_index = dev_addr->bound_dev_if; int bound_if_index = dev_addr->bound_dev_if;
const struct ib_gid_attr *sgid_attr;
int dev_type = dev_addr->dev_type; int dev_type = dev_addr->dev_type;
struct net_device *ndev = NULL; struct net_device *ndev = NULL;
int ret = -ENODEV;
if ((dev_type == ARPHRD_INFINIBAND) && !rdma_protocol_ib(device, port)) 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)) 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)) { if (dev_type == ARPHRD_ETHER && rdma_protocol_roce(device, port)) {
ndev = dev_get_by_index(dev_addr->net, bound_if_index); ndev = dev_get_by_index(dev_addr->net, bound_if_index);
if (!ndev) if (!ndev)
return ret; return ERR_PTR(-ENODEV);
} else { } else {
gid_type = IB_GID_TYPE_IB; gid_type = IB_GID_TYPE_IB;
} }
ret = ib_find_cached_gid_by_port(device, gid, gid_type, port, sgid_attr = rdma_find_gid_by_port(device, gid, gid_type, port, ndev);
ndev, NULL);
if (ndev) if (ndev)
dev_put(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, static int cma_acquire_dev(struct rdma_id_private *id_priv,
struct rdma_id_private *listen_id_priv) struct rdma_id_private *listen_id_priv)
{ {
struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr; 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; struct cma_device *cma_dev;
union ib_gid gid, iboe_gid, *gidp; union ib_gid gid, iboe_gid, *gidp;
enum ib_gid_type gid_type;
enum ib_gid_type default_type;
int ret = -ENODEV; int ret = -ENODEV;
u8 port; u8 port;
...@@ -662,14 +670,15 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv, ...@@ -662,14 +670,15 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv,
port = listen_id_priv->id.port_num; port = listen_id_priv->id.port_num;
gidp = rdma_protocol_roce(cma_dev->device, port) ? gidp = rdma_protocol_roce(cma_dev->device, port) ?
&iboe_gid : &gid; &iboe_gid : &gid;
gid_type = rdma_protocol_ib(cma_dev->device, port) ?
ret = cma_validate_port(cma_dev->device, port, IB_GID_TYPE_IB :
rdma_protocol_ib(cma_dev->device, port) ? listen_id_priv->gid_type;
IB_GID_TYPE_IB : sgid_attr = cma_validate_port(cma_dev->device, port,
listen_id_priv->gid_type, gidp, gid_type, gidp, id_priv);
id_priv); if (!IS_ERR(sgid_attr)) {
if (!ret) {
id_priv->id.port_num = port; id_priv->id.port_num = port;
cma_bind_sgid_attr(id_priv, sgid_attr);
ret = 0;
goto out; goto out;
} }
} }
...@@ -683,14 +692,16 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv, ...@@ -683,14 +692,16 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv,
gidp = rdma_protocol_roce(cma_dev->device, port) ? gidp = rdma_protocol_roce(cma_dev->device, port) ?
&iboe_gid : &gid; &iboe_gid : &gid;
default_type = cma_dev->default_gid_type[port - 1];
ret = cma_validate_port(cma_dev->device, port, gid_type =
rdma_protocol_ib(cma_dev->device, port) ? rdma_protocol_ib(cma_dev->device, port) ?
IB_GID_TYPE_IB : IB_GID_TYPE_IB : default_type;
cma_dev->default_gid_type[port - 1], sgid_attr = cma_validate_port(cma_dev->device, port,
gidp, id_priv); gid_type, gidp, id_priv);
if (!ret) { if (!IS_ERR(sgid_attr)) {
id_priv->id.port_num = port; id_priv->id.port_num = port;
cma_bind_sgid_attr(id_priv, sgid_attr);
ret = 0;
goto out; goto out;
} }
} }
...@@ -1706,6 +1717,10 @@ void rdma_destroy_id(struct rdma_cm_id *id) ...@@ -1706,6 +1717,10 @@ void rdma_destroy_id(struct rdma_cm_id *id)
cma_deref_id(id_priv->id.context); cma_deref_id(id_priv->id.context);
kfree(id_priv->id.route.path_rec); 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); put_net(id_priv->id.route.addr.dev_addr.net);
kfree(id_priv); kfree(id_priv);
} }
......
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
* @bound_dev_if: An optional device interface index. * @bound_dev_if: An optional device interface index.
* @transport: The transport type used. * @transport: The transport type used.
* @net: Network namespace containing the bound_dev_if net_dev. * @net: Network namespace containing the bound_dev_if net_dev.
* @sgid_attr: GID attribute to use for identified SGID
*/ */
struct rdma_dev_addr { struct rdma_dev_addr {
unsigned char src_dev_addr[MAX_ADDR_LEN]; unsigned char src_dev_addr[MAX_ADDR_LEN];
...@@ -67,6 +68,7 @@ struct rdma_dev_addr { ...@@ -67,6 +68,7 @@ struct rdma_dev_addr {
int bound_dev_if; int bound_dev_if;
enum rdma_transport_type transport; enum rdma_transport_type transport;
struct net *net; struct net *net;
const struct ib_gid_attr *sgid_attr;
enum rdma_network_type network; enum rdma_network_type network;
int hoplimit; int hoplimit;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment