Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+41 −26
Original line number Diff line number Diff line
@@ -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,
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) ?
		gid_type = rdma_protocol_ib(cma_dev->device, port) ?
					    IB_GID_TYPE_IB :
					listen_id_priv->gid_type, gidp,
					id_priv);
		if (!ret) {
					    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,
			default_type = cma_dev->default_gid_type[port - 1];
			gid_type =
				rdma_protocol_ib(cma_dev->device, port) ?
						IB_GID_TYPE_IB :
						cma_dev->default_gid_type[port - 1],
						gidp, id_priv);
			if (!ret) {
						 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);
}
+2 −0
Original line number Diff line number Diff line
@@ -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;
};