Commit 08d53976 authored by Leon Romanovsky's avatar Leon Romanovsky Committed by Jason Gunthorpe
Browse files

RDMA/mlx5: Copy response to the user in one place

Update all the places in create QP flows to copy response
to the user in one place.

Link: https://lore.kernel.org/r/20200427154636.381474-34-leon@kernel.org


Reviewed-by: default avatarMaor Gottlieb <maorg@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent 6f2cf76e
Loading
Loading
Loading
Loading
+52 −61
Original line number Diff line number Diff line
@@ -1015,17 +1015,8 @@ static int _create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
		goto err_free;
	}

	err = ib_copy_to_udata(udata, resp, min(udata->outlen, sizeof(*resp)));
	if (err) {
		mlx5_ib_dbg(dev, "copy failed\n");
		goto err_unmap;
	}

	return 0;

err_unmap:
	mlx5_ib_db_unmap_user(context, &qp->db);

err_free:
	kvfree(*in);

@@ -1551,14 +1542,8 @@ static int create_raw_packet_qp(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,

	qp->trans_qp.base.mqp.qpn = qp->sq.wqe_cnt ? sq->base.mqp.qpn :
						     rq->base.mqp.qpn;
	err = ib_copy_to_udata(udata, resp, min(udata->outlen, sizeof(*resp)));
	if (err)
		goto err_destroy_tir;

	return 0;

err_destroy_tir:
	destroy_raw_packet_qp_tir(dev, rq, qp->flags_en, pd);
err_destroy_rq:
	destroy_raw_packet_qp_rq(dev, rq);
err_destroy_sq:
@@ -1618,6 +1603,7 @@ struct mlx5_create_qp_params {
	u8 is_rss_raw : 1;
	struct ib_qp_init_attr *attr;
	u32 uidx;
	struct mlx5_ib_create_qp_resp resp;
};

static int create_rss_raw_qp_tir(struct mlx5_ib_dev *dev, struct ib_pd *pd,
@@ -1629,7 +1615,6 @@ static int create_rss_raw_qp_tir(struct mlx5_ib_dev *dev, struct ib_pd *pd,
	struct ib_udata *udata = params->udata;
	struct mlx5_ib_ucontext *mucontext = rdma_udata_to_drv_context(
		udata, struct mlx5_ib_ucontext, ibucontext);
	struct mlx5_ib_create_qp_resp resp = {};
	int inlen;
	int outlen;
	int err;
@@ -1662,12 +1647,6 @@ static int create_rss_raw_qp_tir(struct mlx5_ib_dev *dev, struct ib_pd *pd,
	if (qp->flags_en & MLX5_QP_FLAG_TIR_ALLOW_SELF_LB_MC)
		lb_flag |= MLX5_TIRC_SELF_LB_BLOCK_BLOCK_MULTICAST;

	err = ib_copy_to_udata(udata, &resp, min(udata->outlen, sizeof(resp)));
	if (err) {
		mlx5_ib_dbg(dev, "copy failed\n");
		return -EINVAL;
	}

	inlen = MLX5_ST_SZ_BYTES(create_tir_in);
	outlen = MLX5_ST_SZ_BYTES(create_tir_out);
	in = kvzalloc(inlen + outlen, GFP_KERNEL);
@@ -1803,34 +1782,30 @@ create_tir:
		goto err;

	if (mucontext->devx_uid) {
		resp.comp_mask |= MLX5_IB_CREATE_QP_RESP_MASK_TIRN;
		resp.tirn = qp->rss_qp.tirn;
		params->resp.comp_mask |= MLX5_IB_CREATE_QP_RESP_MASK_TIRN;
		params->resp.tirn = qp->rss_qp.tirn;
		if (MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, sw_owner)) {
			resp.tir_icm_addr =
			params->resp.tir_icm_addr =
				MLX5_GET(create_tir_out, out, icm_address_31_0);
			resp.tir_icm_addr |= (u64)MLX5_GET(create_tir_out, out,
			params->resp.tir_icm_addr |=
				(u64)MLX5_GET(create_tir_out, out,
					      icm_address_39_32)
				<< 32;
			resp.tir_icm_addr |= (u64)MLX5_GET(create_tir_out, out,
			params->resp.tir_icm_addr |=
				(u64)MLX5_GET(create_tir_out, out,
					      icm_address_63_40)
				<< 40;
			resp.comp_mask |=
			params->resp.comp_mask |=
				MLX5_IB_CREATE_QP_RESP_MASK_TIR_ICM_ADDR;
		}
	}

	err = ib_copy_to_udata(udata, &resp, min(udata->outlen, sizeof(resp)));
	if (err)
		goto err_copy;

	kvfree(in);
	/* qpn is reserved for that QP */
	qp->trans_qp.base.mqp.qpn = 0;
	qp->is_rss = true;
	return 0;

err_copy:
	mlx5_cmd_destroy_tir(dev->mdev, qp->rss_qp.tirn, mucontext->devx_uid);
err:
	kvfree(in);
	return err;
@@ -1995,7 +1970,6 @@ static int create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
	struct mlx5_ib_resources *devr = &dev->devr;
	int inlen = MLX5_ST_SZ_BYTES(create_qp_in);
	struct mlx5_core_dev *mdev = dev->mdev;
	struct mlx5_ib_create_qp_resp resp = {};
	struct mlx5_ib_cq *send_cq;
	struct mlx5_ib_cq *recv_cq;
	unsigned long flags;
@@ -2038,8 +2012,8 @@ static int create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
	if (ucmd->sq_wqe_count > (1 << MLX5_CAP_GEN(mdev, log_max_qp_sz)))
		return -EINVAL;

	err = _create_user_qp(dev, pd, qp, udata, init_attr, &in, &resp, &inlen,
			      base, ucmd);
	err = _create_user_qp(dev, pd, qp, udata, init_attr, &in, &params->resp,
			      &inlen, base, ucmd);
	if (err)
		return err;

@@ -2139,7 +2113,7 @@ static int create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
		qp->raw_packet_qp.sq.ubuffer.buf_addr = ucmd->sq_buf_addr;
		raw_packet_qp_copy_info(qp, &qp->raw_packet_qp);
		err = create_raw_packet_qp(dev, qp, in, inlen, pd, udata,
					   &resp);
					   &params->resp);
	} else
		err = mlx5_core_create_qp(dev, &base->mqp, in, inlen);

@@ -2865,6 +2839,25 @@ static int get_qp_uidx(struct mlx5_ib_qp *qp,
	return get_qp_user_index(ucontext, ucmd, sizeof(*ucmd), &params->uidx);
}

static int mlx5_ib_destroy_dct(struct mlx5_ib_qp *mqp)
{
	struct mlx5_ib_dev *dev = to_mdev(mqp->ibqp.device);

	if (mqp->state == IB_QPS_RTR) {
		int err;

		err = mlx5_core_destroy_dct(dev, &mqp->dct.mdct);
		if (err) {
			mlx5_ib_warn(dev, "failed to destroy DCT %d\n", err);
			return err;
		}
	}

	kfree(mqp->dct.in);
	kfree(mqp);
	return 0;
}

struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attr,
				struct ib_udata *udata)
{
@@ -2955,6 +2948,7 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attr,
	}

	kfree(params.ucmd);
	params.ucmd = NULL;

	if (is_qp0(attr->qp_type))
		qp->ibqp.qp_num = 0;
@@ -2965,8 +2959,24 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attr,

	qp->trans_qp.xrcdn = xrcdn;

	if (udata)
		/*
		 * It is safe to copy response for all user create QP flows,
		 * including MLX5_IB_QPT_DCT, which doesn't need it.
		 * In that case, resp will be filled with zeros.
		 */
		err = ib_copy_to_udata(udata, &params.resp, params.outlen);
	if (err)
		goto destroy_qp;

	return &qp->ibqp;

destroy_qp:
	if (qp->type == MLX5_IB_QPT_DCT)
		mlx5_ib_destroy_dct(qp);
	else
		destroy_qp_common(dev, qp, udata);
	qp = NULL;
free_qp:
	kfree(qp);
free_ucmd:
@@ -2974,25 +2984,6 @@ free_ucmd:
	return ERR_PTR(err);
}

static int mlx5_ib_destroy_dct(struct mlx5_ib_qp *mqp)
{
	struct mlx5_ib_dev *dev = to_mdev(mqp->ibqp.device);

	if (mqp->state == IB_QPS_RTR) {
		int err;

		err = mlx5_core_destroy_dct(dev, &mqp->dct.mdct);
		if (err) {
			mlx5_ib_warn(dev, "failed to destroy DCT %d\n", err);
			return err;
		}
	}

	kfree(mqp->dct.in);
	kfree(mqp);
	return 0;
}

int mlx5_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
{
	struct mlx5_ib_dev *dev = to_mdev(qp->device);