Commit 8fd3cd2a authored by Leon Romanovsky's avatar Leon Romanovsky Committed by Jason Gunthorpe
Browse files

RDMA/mlx4: Prepare QP allocation to remove from the driver

Since all mlx4 QP have same storage type, move the QP allocation to be in
one place. This change is preparation to removal of such allocation from
the driver.

Link: https://lore.kernel.org/r/20200926102450.2966017-7-leon@kernel.org


Reviewed-by: default avatarMaor Gottlieb <maorg@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leonro@nvidia.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
parent 915ec7ed
Loading
Loading
Loading
Loading
+63 −94
Original line number Original line Diff line number Diff line
@@ -630,8 +630,6 @@ static int create_qp_rss(struct mlx4_ib_dev *dev,
	if (err)
	if (err)
		goto err_qpn;
		goto err_qpn;


	mutex_init(&qp->mutex);

	INIT_LIST_HEAD(&qp->gid_list);
	INIT_LIST_HEAD(&qp->gid_list);
	INIT_LIST_HEAD(&qp->steering_rules);
	INIT_LIST_HEAD(&qp->steering_rules);


@@ -670,80 +668,72 @@ static int create_qp_rss(struct mlx4_ib_dev *dev,
	return err;
	return err;
}
}


static struct ib_qp *_mlx4_ib_create_qp_rss(struct ib_pd *pd,
static int _mlx4_ib_create_qp_rss(struct ib_pd *pd, struct mlx4_ib_qp *qp,
				  struct ib_qp_init_attr *init_attr,
				  struct ib_qp_init_attr *init_attr,
				  struct ib_udata *udata)
				  struct ib_udata *udata)
{
{
	struct mlx4_ib_qp *qp;
	struct mlx4_ib_create_qp_rss ucmd = {};
	struct mlx4_ib_create_qp_rss ucmd = {};
	size_t required_cmd_sz;
	size_t required_cmd_sz;
	int err;
	int err;


	if (!udata) {
	if (!udata) {
		pr_debug("RSS QP with NULL udata\n");
		pr_debug("RSS QP with NULL udata\n");
		return ERR_PTR(-EINVAL);
		return -EINVAL;
	}
	}


	if (udata->outlen)
	if (udata->outlen)
		return ERR_PTR(-EOPNOTSUPP);
		return -EOPNOTSUPP;


	required_cmd_sz = offsetof(typeof(ucmd), reserved1) +
	required_cmd_sz = offsetof(typeof(ucmd), reserved1) +
					sizeof(ucmd.reserved1);
					sizeof(ucmd.reserved1);
	if (udata->inlen < required_cmd_sz) {
	if (udata->inlen < required_cmd_sz) {
		pr_debug("invalid inlen\n");
		pr_debug("invalid inlen\n");
		return ERR_PTR(-EINVAL);
		return -EINVAL;
	}
	}


	if (ib_copy_from_udata(&ucmd, udata, min(sizeof(ucmd), udata->inlen))) {
	if (ib_copy_from_udata(&ucmd, udata, min(sizeof(ucmd), udata->inlen))) {
		pr_debug("copy failed\n");
		pr_debug("copy failed\n");
		return ERR_PTR(-EFAULT);
		return -EFAULT;
	}
	}


	if (memchr_inv(ucmd.reserved, 0, sizeof(ucmd.reserved)))
	if (memchr_inv(ucmd.reserved, 0, sizeof(ucmd.reserved)))
		return ERR_PTR(-EOPNOTSUPP);
		return -EOPNOTSUPP;


	if (ucmd.comp_mask || ucmd.reserved1)
	if (ucmd.comp_mask || ucmd.reserved1)
		return ERR_PTR(-EOPNOTSUPP);
		return -EOPNOTSUPP;


	if (udata->inlen > sizeof(ucmd) &&
	if (udata->inlen > sizeof(ucmd) &&
	    !ib_is_udata_cleared(udata, sizeof(ucmd),
	    !ib_is_udata_cleared(udata, sizeof(ucmd),
				 udata->inlen - sizeof(ucmd))) {
				 udata->inlen - sizeof(ucmd))) {
		pr_debug("inlen is not supported\n");
		pr_debug("inlen is not supported\n");
		return ERR_PTR(-EOPNOTSUPP);
		return -EOPNOTSUPP;
	}
	}


	if (init_attr->qp_type != IB_QPT_RAW_PACKET) {
	if (init_attr->qp_type != IB_QPT_RAW_PACKET) {
		pr_debug("RSS QP with unsupported QP type %d\n",
		pr_debug("RSS QP with unsupported QP type %d\n",
			 init_attr->qp_type);
			 init_attr->qp_type);
		return ERR_PTR(-EOPNOTSUPP);
		return -EOPNOTSUPP;
	}
	}


	if (init_attr->create_flags) {
	if (init_attr->create_flags) {
		pr_debug("RSS QP doesn't support create flags\n");
		pr_debug("RSS QP doesn't support create flags\n");
		return ERR_PTR(-EOPNOTSUPP);
		return -EOPNOTSUPP;
	}
	}


	if (init_attr->send_cq || init_attr->cap.max_send_wr) {
	if (init_attr->send_cq || init_attr->cap.max_send_wr) {
		pr_debug("RSS QP with unsupported send attributes\n");
		pr_debug("RSS QP with unsupported send attributes\n");
		return ERR_PTR(-EOPNOTSUPP);
		return -EOPNOTSUPP;
	}
	}


	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
	if (!qp)
		return ERR_PTR(-ENOMEM);

	qp->pri.vid = 0xFFFF;
	qp->pri.vid = 0xFFFF;
	qp->alt.vid = 0xFFFF;
	qp->alt.vid = 0xFFFF;


	err = create_qp_rss(to_mdev(pd->device), init_attr, &ucmd, qp);
	err = create_qp_rss(to_mdev(pd->device), init_attr, &ucmd, qp);
	if (err) {
	if (err)
		kfree(qp);
		return err;
		return ERR_PTR(err);
	}


	qp->ibqp.qp_num = qp->mqp.qpn;
	qp->ibqp.qp_num = qp->mqp.qpn;

	return 0;
	return &qp->ibqp;
}
}


/*
/*
@@ -847,7 +837,6 @@ static int create_rq(struct ib_pd *pd, struct ib_qp_init_attr *init_attr,


	qp->mlx4_ib_qp_type = MLX4_IB_QPT_RAW_PACKET;
	qp->mlx4_ib_qp_type = MLX4_IB_QPT_RAW_PACKET;


	mutex_init(&qp->mutex);
	spin_lock_init(&qp->sq.lock);
	spin_lock_init(&qp->sq.lock);
	spin_lock_init(&qp->rq.lock);
	spin_lock_init(&qp->rq.lock);
	INIT_LIST_HEAD(&qp->gid_list);
	INIT_LIST_HEAD(&qp->gid_list);
@@ -962,12 +951,11 @@ static int create_rq(struct ib_pd *pd, struct ib_qp_init_attr *init_attr,


static int create_qp_common(struct ib_pd *pd, struct ib_qp_init_attr *init_attr,
static int create_qp_common(struct ib_pd *pd, struct ib_qp_init_attr *init_attr,
			    struct ib_udata *udata, int sqpn,
			    struct ib_udata *udata, int sqpn,
			    struct mlx4_ib_qp **caller_qp)
			    struct mlx4_ib_qp *qp)
{
{
	struct mlx4_ib_dev *dev = to_mdev(pd->device);
	struct mlx4_ib_dev *dev = to_mdev(pd->device);
	int qpn;
	int qpn;
	int err;
	int err;
	struct mlx4_ib_qp *qp;
	struct mlx4_ib_ucontext *context = rdma_udata_to_drv_context(
	struct mlx4_ib_ucontext *context = rdma_udata_to_drv_context(
		udata, struct mlx4_ib_ucontext, ibucontext);
		udata, struct mlx4_ib_ucontext, ibucontext);
	enum mlx4_ib_qp_type qp_type = (enum mlx4_ib_qp_type) init_attr->qp_type;
	enum mlx4_ib_qp_type qp_type = (enum mlx4_ib_qp_type) init_attr->qp_type;
@@ -1015,28 +1003,18 @@ static int create_qp_common(struct ib_pd *pd, struct ib_qp_init_attr *init_attr,
		sqpn = qpn;
		sqpn = qpn;
	}
	}


	if (!*caller_qp) {
	if (init_attr->qp_type == IB_QPT_SMI ||
		qp = kzalloc(sizeof(struct mlx4_ib_qp), GFP_KERNEL);
	    init_attr->qp_type == IB_QPT_GSI || qp_type == MLX4_IB_QPT_SMI ||
		if (!qp)
	    qp_type == MLX4_IB_QPT_GSI ||
			return -ENOMEM;

		if (qp_type == MLX4_IB_QPT_SMI || qp_type == MLX4_IB_QPT_GSI ||
	    (qp_type & (MLX4_IB_QPT_PROXY_SMI | MLX4_IB_QPT_PROXY_SMI_OWNER |
	    (qp_type & (MLX4_IB_QPT_PROXY_SMI | MLX4_IB_QPT_PROXY_SMI_OWNER |
			MLX4_IB_QPT_PROXY_GSI | MLX4_IB_QPT_TUN_SMI_OWNER))) {
			MLX4_IB_QPT_PROXY_GSI | MLX4_IB_QPT_TUN_SMI_OWNER))) {
		qp->sqp = kzalloc(sizeof(struct mlx4_ib_sqp), GFP_KERNEL);
		qp->sqp = kzalloc(sizeof(struct mlx4_ib_sqp), GFP_KERNEL);
			if (!qp->sqp) {
		if (!qp->sqp)
				kfree(qp);
			return -ENOMEM;
			return -ENOMEM;
	}
	}
		}
		qp->pri.vid = 0xFFFF;
		qp->alt.vid = 0xFFFF;
	} else
		qp = *caller_qp;


	qp->mlx4_ib_qp_type = qp_type;
	qp->mlx4_ib_qp_type = qp_type;


	mutex_init(&qp->mutex);
	spin_lock_init(&qp->sq.lock);
	spin_lock_init(&qp->sq.lock);
	spin_lock_init(&qp->rq.lock);
	spin_lock_init(&qp->rq.lock);
	INIT_LIST_HEAD(&qp->gid_list);
	INIT_LIST_HEAD(&qp->gid_list);
@@ -1211,9 +1189,6 @@ static int create_qp_common(struct ib_pd *pd, struct ib_qp_init_attr *init_attr,


	qp->mqp.event = mlx4_ib_qp_event;
	qp->mqp.event = mlx4_ib_qp_event;


	if (!*caller_qp)
		*caller_qp = qp;

	spin_lock_irqsave(&dev->reset_flow_resource_lock, flags);
	spin_lock_irqsave(&dev->reset_flow_resource_lock, flags);
	mlx4_ib_lock_cqs(to_mcq(init_attr->send_cq),
	mlx4_ib_lock_cqs(to_mcq(init_attr->send_cq),
			 to_mcq(init_attr->recv_cq));
			 to_mcq(init_attr->recv_cq));
@@ -1265,11 +1240,7 @@ static int create_qp_common(struct ib_pd *pd, struct ib_qp_init_attr *init_attr,
		mlx4_db_free(dev->dev, &qp->db);
		mlx4_db_free(dev->dev, &qp->db);


err:
err:
	if (!*caller_qp) {
	kfree(qp->sqp);
	kfree(qp->sqp);
		kfree(qp);
	}

	return err;
	return err;
}
}


@@ -1383,7 +1354,6 @@ static void destroy_qp_rss(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp)
	mlx4_qp_free(dev->dev, &qp->mqp);
	mlx4_qp_free(dev->dev, &qp->mqp);
	mlx4_qp_release_range(dev->dev, qp->mqp.qpn, 1);
	mlx4_qp_release_range(dev->dev, qp->mqp.qpn, 1);
	del_gid_entries(qp);
	del_gid_entries(qp);
	kfree(qp->rss_ctx);
}
}


static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
@@ -1502,17 +1472,16 @@ static u32 get_sqp_num(struct mlx4_ib_dev *dev, struct ib_qp_init_attr *attr)
		return dev->dev->caps.spec_qps[attr->port_num - 1].qp1_proxy;
		return dev->dev->caps.spec_qps[attr->port_num - 1].qp1_proxy;
}
}


static struct ib_qp *_mlx4_ib_create_qp(struct ib_pd *pd,
static int _mlx4_ib_create_qp(struct ib_pd *pd, struct mlx4_ib_qp *qp,
			      struct ib_qp_init_attr *init_attr,
			      struct ib_qp_init_attr *init_attr,
			      struct ib_udata *udata)
			      struct ib_udata *udata)
{
{
	struct mlx4_ib_qp *qp = NULL;
	int err;
	int err;
	int sup_u_create_flags = MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK;
	int sup_u_create_flags = MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK;
	u16 xrcdn = 0;
	u16 xrcdn = 0;


	if (init_attr->rwq_ind_tbl)
	if (init_attr->rwq_ind_tbl)
		return _mlx4_ib_create_qp_rss(pd, init_attr, udata);
		return _mlx4_ib_create_qp_rss(pd, qp, init_attr, udata);


	/*
	/*
	 * We only support LSO, vendor flag1, and multicast loopback blocking,
	 * We only support LSO, vendor flag1, and multicast loopback blocking,
@@ -1524,16 +1493,16 @@ static struct ib_qp *_mlx4_ib_create_qp(struct ib_pd *pd,
					MLX4_IB_SRIOV_SQP |
					MLX4_IB_SRIOV_SQP |
					MLX4_IB_QP_NETIF |
					MLX4_IB_QP_NETIF |
					MLX4_IB_QP_CREATE_ROCE_V2_GSI))
					MLX4_IB_QP_CREATE_ROCE_V2_GSI))
		return ERR_PTR(-EINVAL);
		return -EINVAL;


	if (init_attr->create_flags & IB_QP_CREATE_NETIF_QP) {
	if (init_attr->create_flags & IB_QP_CREATE_NETIF_QP) {
		if (init_attr->qp_type != IB_QPT_UD)
		if (init_attr->qp_type != IB_QPT_UD)
			return ERR_PTR(-EINVAL);
			return -EINVAL;
	}
	}


	if (init_attr->create_flags) {
	if (init_attr->create_flags) {
		if (udata && init_attr->create_flags & ~(sup_u_create_flags))
		if (udata && init_attr->create_flags & ~(sup_u_create_flags))
			return ERR_PTR(-EINVAL);
			return -EINVAL;


		if ((init_attr->create_flags & ~(MLX4_IB_SRIOV_SQP |
		if ((init_attr->create_flags & ~(MLX4_IB_SRIOV_SQP |
						 MLX4_IB_QP_CREATE_ROCE_V2_GSI  |
						 MLX4_IB_QP_CREATE_ROCE_V2_GSI  |
@@ -1543,7 +1512,7 @@ static struct ib_qp *_mlx4_ib_create_qp(struct ib_pd *pd,
		     init_attr->qp_type > IB_QPT_GSI) ||
		     init_attr->qp_type > IB_QPT_GSI) ||
		    (init_attr->create_flags & MLX4_IB_QP_CREATE_ROCE_V2_GSI &&
		    (init_attr->create_flags & MLX4_IB_QP_CREATE_ROCE_V2_GSI &&
		     init_attr->qp_type != IB_QPT_GSI))
		     init_attr->qp_type != IB_QPT_GSI))
			return ERR_PTR(-EINVAL);
			return -EINVAL;
	}
	}


	switch (init_attr->qp_type) {
	switch (init_attr->qp_type) {
@@ -1554,31 +1523,22 @@ static struct ib_qp *_mlx4_ib_create_qp(struct ib_pd *pd,
		fallthrough;
		fallthrough;
	case IB_QPT_XRC_INI:
	case IB_QPT_XRC_INI:
		if (!(to_mdev(pd->device)->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC))
		if (!(to_mdev(pd->device)->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC))
			return ERR_PTR(-ENOSYS);
			return -ENOSYS;
		init_attr->recv_cq = init_attr->send_cq;
		init_attr->recv_cq = init_attr->send_cq;
		fallthrough;
		fallthrough;
	case IB_QPT_RC:
	case IB_QPT_RC:
	case IB_QPT_UC:
	case IB_QPT_UC:
	case IB_QPT_RAW_PACKET:
	case IB_QPT_RAW_PACKET:
		qp = kzalloc(sizeof(*qp), GFP_KERNEL);
	case IB_QPT_UD:
		if (!qp)
			return ERR_PTR(-ENOMEM);
		qp->pri.vid = 0xFFFF;
		qp->pri.vid = 0xFFFF;
		qp->alt.vid = 0xFFFF;
		qp->alt.vid = 0xFFFF;
		fallthrough;
		err = create_qp_common(pd, init_attr, udata, 0, qp);
	case IB_QPT_UD:
		if (err)
	{
			return err;
		err = create_qp_common(pd, init_attr, udata, 0, &qp);
		if (err) {
			kfree(qp);
			return ERR_PTR(err);
		}


		qp->ibqp.qp_num = qp->mqp.qpn;
		qp->ibqp.qp_num = qp->mqp.qpn;
		qp->xrcdn = xrcdn;
		qp->xrcdn = xrcdn;

		break;
		break;
	}
	case IB_QPT_SMI:
	case IB_QPT_SMI:
	case IB_QPT_GSI:
	case IB_QPT_GSI:
	{
	{
@@ -1586,21 +1546,23 @@ static struct ib_qp *_mlx4_ib_create_qp(struct ib_pd *pd,


		/* Userspace is not allowed to create special QPs: */
		/* Userspace is not allowed to create special QPs: */
		if (udata)
		if (udata)
			return ERR_PTR(-EINVAL);
			return -EINVAL;
		if (init_attr->create_flags & MLX4_IB_QP_CREATE_ROCE_V2_GSI) {
		if (init_attr->create_flags & MLX4_IB_QP_CREATE_ROCE_V2_GSI) {
			int res = mlx4_qp_reserve_range(to_mdev(pd->device)->dev,
			int res = mlx4_qp_reserve_range(to_mdev(pd->device)->dev,
							1, 1, &sqpn, 0,
							1, 1, &sqpn, 0,
							MLX4_RES_USAGE_DRIVER);
							MLX4_RES_USAGE_DRIVER);


			if (res)
			if (res)
				return ERR_PTR(res);
				return res;
		} else {
		} else {
			sqpn = get_sqp_num(to_mdev(pd->device), init_attr);
			sqpn = get_sqp_num(to_mdev(pd->device), init_attr);
		}
		}


		err = create_qp_common(pd, init_attr, udata, sqpn, &qp);
		qp->pri.vid = 0xFFFF;
		qp->alt.vid = 0xFFFF;
		err = create_qp_common(pd, init_attr, udata, sqpn, qp);
		if (err)
		if (err)
			return ERR_PTR(err);
			return err;


		qp->port	= init_attr->port_num;
		qp->port	= init_attr->port_num;
		qp->ibqp.qp_num = init_attr->qp_type == IB_QPT_SMI ? 0 :
		qp->ibqp.qp_num = init_attr->qp_type == IB_QPT_SMI ? 0 :
@@ -1609,25 +1571,32 @@ static struct ib_qp *_mlx4_ib_create_qp(struct ib_pd *pd,
	}
	}
	default:
	default:
		/* Don't support raw QPs */
		/* Don't support raw QPs */
		return ERR_PTR(-EOPNOTSUPP);
		return -EOPNOTSUPP;
	}
	}

	return 0;
	return &qp->ibqp;
}
}


struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
				struct ib_qp_init_attr *init_attr,
				struct ib_qp_init_attr *init_attr,
				struct ib_udata *udata) {
				struct ib_udata *udata) {
	struct ib_device *device = pd ? pd->device : init_attr->xrcd->device;
	struct ib_device *device = pd ? pd->device : init_attr->xrcd->device;
	struct ib_qp *ibqp;
	struct mlx4_ib_dev *dev = to_mdev(device);
	struct mlx4_ib_dev *dev = to_mdev(device);
	struct mlx4_ib_qp *qp;
	int ret;

	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
	if (!qp)
		return ERR_PTR(-ENOMEM);


	ibqp = _mlx4_ib_create_qp(pd, init_attr, udata);
	mutex_init(&qp->mutex);
	ret = _mlx4_ib_create_qp(pd, qp, init_attr, udata);
	if (ret) {
		kfree(qp);
		return ERR_PTR(ret);
	}


	if (!IS_ERR(ibqp) &&
	if (init_attr->qp_type == IB_QPT_GSI &&
	    (init_attr->qp_type == IB_QPT_GSI) &&
	    !(init_attr->create_flags & MLX4_IB_QP_CREATE_ROCE_V2_GSI)) {
	    !(init_attr->create_flags & MLX4_IB_QP_CREATE_ROCE_V2_GSI)) {
		struct mlx4_ib_qp *qp = to_mqp(ibqp);
		struct mlx4_ib_sqp *sqp = qp->sqp;
		struct mlx4_ib_sqp *sqp = qp->sqp;
		int is_eth = rdma_cap_eth_ah(&dev->ib_dev, init_attr->port_num);
		int is_eth = rdma_cap_eth_ah(&dev->ib_dev, init_attr->port_num);


@@ -1647,7 +1616,7 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
			init_attr->create_flags &= ~MLX4_IB_QP_CREATE_ROCE_V2_GSI;
			init_attr->create_flags &= ~MLX4_IB_QP_CREATE_ROCE_V2_GSI;
		}
		}
	}
	}
	return ibqp;
	return &qp->ibqp;
}
}


static int _mlx4_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
static int _mlx4_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
@@ -1674,7 +1643,6 @@ static int _mlx4_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
		destroy_qp_common(dev, mqp, MLX4_IB_QP_SRC, udata);
		destroy_qp_common(dev, mqp, MLX4_IB_QP_SRC, udata);
	}
	}


	if (is_sqp(dev, mqp))
	kfree(mqp->sqp);
	kfree(mqp->sqp);
	kfree(mqp);
	kfree(mqp);


@@ -4156,6 +4124,7 @@ struct ib_wq *mlx4_ib_create_wq(struct ib_pd *pd,
	if (!qp)
	if (!qp)
		return ERR_PTR(-ENOMEM);
		return ERR_PTR(-ENOMEM);


	mutex_init(&qp->mutex);
	qp->pri.vid = 0xFFFF;
	qp->pri.vid = 0xFFFF;
	qp->alt.vid = 0xFFFF;
	qp->alt.vid = 0xFFFF;