IB/mlx5: Add support for QP with a given source QPN
Allow user space applications to accelerate send and receive traffic which is typically handled by IPoIB ULP by creating a UD QP with a given source QPN of the IPoIB UD QP. UD QP with a given source QPN should basically be similar to RAW QP from point of view of its created resources. However, - Its TIS should point to the source QPN. - Modify can be done only on its state as the transport attributes are managed by its source QP. This patch manages below: - Creating/destroying/modifying UD QP with a given source QPN. Signed-off-by: Yishai Hadas <yishaih@mellanox.com> Reviewed-by: Maor Gottlieb <maorg@mellanox.com> Signed-off-by: Leon Romanovsky <leon@kernel.org> Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
parent
2dee0e5458
commit
c2e53b2ce1
|
@ -383,6 +383,7 @@ struct mlx5_ib_qp {
|
|||
struct list_head cq_recv_list;
|
||||
struct list_head cq_send_list;
|
||||
u32 rate_limit;
|
||||
u32 underlay_qpn;
|
||||
};
|
||||
|
||||
struct mlx5_ib_cq_buf {
|
||||
|
@ -404,6 +405,7 @@ enum mlx5_ib_qp_flags {
|
|||
MLX5_IB_QP_CAP_SCATTER_FCS = 1 << 7,
|
||||
MLX5_IB_QP_RSS = 1 << 8,
|
||||
MLX5_IB_QP_CVLAN_STRIPPING = 1 << 9,
|
||||
MLX5_IB_QP_UNDERLAY = 1 << 10,
|
||||
};
|
||||
|
||||
struct mlx5_umr_wr {
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <rdma/ib_umem.h>
|
||||
#include <rdma/ib_cache.h>
|
||||
#include <rdma/ib_user_verbs.h>
|
||||
#include <linux/mlx5/fs.h>
|
||||
#include "mlx5_ib.h"
|
||||
|
||||
/* not supported currently */
|
||||
|
@ -453,7 +454,8 @@ static int set_user_buf_size(struct mlx5_ib_dev *dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (attr->qp_type == IB_QPT_RAW_PACKET) {
|
||||
if (attr->qp_type == IB_QPT_RAW_PACKET ||
|
||||
qp->flags & MLX5_IB_QP_UNDERLAY) {
|
||||
base->ubuffer.buf_size = qp->rq.wqe_cnt << qp->rq.wqe_shift;
|
||||
qp->raw_packet_qp.sq.ubuffer.buf_size = qp->sq.wqe_cnt << 6;
|
||||
} else {
|
||||
|
@ -1025,12 +1027,16 @@ static int is_connected(enum ib_qp_type qp_type)
|
|||
}
|
||||
|
||||
static int create_raw_packet_qp_tis(struct mlx5_ib_dev *dev,
|
||||
struct mlx5_ib_qp *qp,
|
||||
struct mlx5_ib_sq *sq, u32 tdn)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(create_tis_in)] = {0};
|
||||
void *tisc = MLX5_ADDR_OF(create_tis_in, in, ctx);
|
||||
|
||||
MLX5_SET(tisc, tisc, transport_domain, tdn);
|
||||
if (qp->flags & MLX5_IB_QP_UNDERLAY)
|
||||
MLX5_SET(tisc, tisc, underlay_qpn, qp->underlay_qpn);
|
||||
|
||||
return mlx5_core_create_tis(dev->mdev, in, sizeof(in), &sq->tisn);
|
||||
}
|
||||
|
||||
|
@ -1233,7 +1239,7 @@ static int create_raw_packet_qp(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
|
|||
u32 tdn = mucontext->tdn;
|
||||
|
||||
if (qp->sq.wqe_cnt) {
|
||||
err = create_raw_packet_qp_tis(dev, sq, tdn);
|
||||
err = create_raw_packet_qp_tis(dev, qp, sq, tdn);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -1506,10 +1512,6 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
|
|||
u32 *in;
|
||||
int err;
|
||||
|
||||
base = init_attr->qp_type == IB_QPT_RAW_PACKET ?
|
||||
&qp->raw_packet_qp.rq.base :
|
||||
&qp->trans_qp.base;
|
||||
|
||||
mutex_init(&qp->mutex);
|
||||
spin_lock_init(&qp->sq.lock);
|
||||
spin_lock_init(&qp->rq.lock);
|
||||
|
@ -1591,10 +1593,28 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
|
|||
|
||||
qp->wq_sig = !!(ucmd.flags & MLX5_QP_FLAG_SIGNATURE);
|
||||
qp->scat_cqe = !!(ucmd.flags & MLX5_QP_FLAG_SCATTER_CQE);
|
||||
|
||||
if (init_attr->create_flags & IB_QP_CREATE_SOURCE_QPN) {
|
||||
if (init_attr->qp_type != IB_QPT_UD ||
|
||||
(MLX5_CAP_GEN(dev->mdev, port_type) !=
|
||||
MLX5_CAP_PORT_TYPE_IB) ||
|
||||
!mlx5_get_flow_namespace(dev->mdev, MLX5_FLOW_NAMESPACE_BYPASS)) {
|
||||
mlx5_ib_dbg(dev, "Source QP option isn't supported\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
qp->flags |= MLX5_IB_QP_UNDERLAY;
|
||||
qp->underlay_qpn = init_attr->source_qpn;
|
||||
}
|
||||
} else {
|
||||
qp->wq_sig = !!wq_signature;
|
||||
}
|
||||
|
||||
base = (init_attr->qp_type == IB_QPT_RAW_PACKET ||
|
||||
qp->flags & MLX5_IB_QP_UNDERLAY) ?
|
||||
&qp->raw_packet_qp.rq.base :
|
||||
&qp->trans_qp.base;
|
||||
|
||||
qp->has_rq = qp_has_rq(init_attr);
|
||||
err = set_rq_size(dev, &init_attr->cap, qp->has_rq,
|
||||
qp, (pd && pd->uobject) ? &ucmd : NULL);
|
||||
|
@ -1745,7 +1765,8 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
|
|||
qp->flags |= MLX5_IB_QP_LSO;
|
||||
}
|
||||
|
||||
if (init_attr->qp_type == IB_QPT_RAW_PACKET) {
|
||||
if (init_attr->qp_type == IB_QPT_RAW_PACKET ||
|
||||
qp->flags & MLX5_IB_QP_UNDERLAY) {
|
||||
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, pd);
|
||||
|
@ -1897,7 +1918,7 @@ static int modify_raw_packet_qp(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
|
|||
static void destroy_qp_common(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp)
|
||||
{
|
||||
struct mlx5_ib_cq *send_cq, *recv_cq;
|
||||
struct mlx5_ib_qp_base *base = &qp->trans_qp.base;
|
||||
struct mlx5_ib_qp_base *base;
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
|
@ -1906,12 +1927,14 @@ static void destroy_qp_common(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp)
|
|||
return;
|
||||
}
|
||||
|
||||
base = qp->ibqp.qp_type == IB_QPT_RAW_PACKET ?
|
||||
base = (qp->ibqp.qp_type == IB_QPT_RAW_PACKET ||
|
||||
qp->flags & MLX5_IB_QP_UNDERLAY) ?
|
||||
&qp->raw_packet_qp.rq.base :
|
||||
&qp->trans_qp.base;
|
||||
|
||||
if (qp->state != IB_QPS_RESET) {
|
||||
if (qp->ibqp.qp_type != IB_QPT_RAW_PACKET) {
|
||||
if (qp->ibqp.qp_type != IB_QPT_RAW_PACKET &&
|
||||
!(qp->flags & MLX5_IB_QP_UNDERLAY)) {
|
||||
err = mlx5_core_qp_modify(dev->mdev,
|
||||
MLX5_CMD_OP_2RST_QP, 0,
|
||||
NULL, &base->mqp);
|
||||
|
@ -1950,7 +1973,8 @@ static void destroy_qp_common(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp)
|
|||
mlx5_ib_unlock_cqs(send_cq, recv_cq);
|
||||
spin_unlock_irqrestore(&dev->reset_flow_resource_lock, flags);
|
||||
|
||||
if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET) {
|
||||
if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET ||
|
||||
qp->flags & MLX5_IB_QP_UNDERLAY) {
|
||||
destroy_raw_packet_qp(dev, qp);
|
||||
} else {
|
||||
err = mlx5_core_destroy_qp(dev->mdev, &base->mqp);
|
||||
|
@ -2706,7 +2730,8 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
|
|||
|
||||
if (is_sqp(ibqp->qp_type)) {
|
||||
context->mtu_msgmax = (IB_MTU_256 << 5) | 8;
|
||||
} else if (ibqp->qp_type == IB_QPT_UD ||
|
||||
} else if ((ibqp->qp_type == IB_QPT_UD &&
|
||||
!(qp->flags & MLX5_IB_QP_UNDERLAY)) ||
|
||||
ibqp->qp_type == MLX5_IB_QPT_REG_UMR) {
|
||||
context->mtu_msgmax = (IB_MTU_4096 << 5) | 12;
|
||||
} else if (attr_mask & IB_QP_PATH_MTU) {
|
||||
|
@ -2803,6 +2828,11 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
|
|||
if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) {
|
||||
u8 port_num = (attr_mask & IB_QP_PORT ? attr->port_num :
|
||||
qp->port) - 1;
|
||||
|
||||
/* Underlay port should be used - index 0 function per port */
|
||||
if (qp->flags & MLX5_IB_QP_UNDERLAY)
|
||||
port_num = 0;
|
||||
|
||||
mibport = &dev->port[port_num];
|
||||
context->qp_counter_set_usr_page |=
|
||||
cpu_to_be32((u32)(mibport->cnts.set_id) << 24);
|
||||
|
@ -2828,7 +2858,8 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
|
|||
optpar = ib_mask_to_mlx5_opt(attr_mask);
|
||||
optpar &= opt_mask[mlx5_cur][mlx5_new][mlx5_st];
|
||||
|
||||
if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET) {
|
||||
if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET ||
|
||||
qp->flags & MLX5_IB_QP_UNDERLAY) {
|
||||
struct mlx5_modify_raw_qp_param raw_qp_param = {};
|
||||
|
||||
raw_qp_param.operation = op;
|
||||
|
@ -2917,7 +2948,13 @@ int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
|||
ll = dev->ib_dev.get_link_layer(&dev->ib_dev, port);
|
||||
}
|
||||
|
||||
if (qp_type != MLX5_IB_QPT_REG_UMR &&
|
||||
if (qp->flags & MLX5_IB_QP_UNDERLAY) {
|
||||
if (attr_mask & ~(IB_QP_STATE | IB_QP_CUR_STATE)) {
|
||||
mlx5_ib_dbg(dev, "invalid attr_mask 0x%x when underlay QP is used\n",
|
||||
attr_mask);
|
||||
goto out;
|
||||
}
|
||||
} else if (qp_type != MLX5_IB_QPT_REG_UMR &&
|
||||
!ib_modify_qp_is_ok(cur_state, new_state, qp_type, attr_mask, ll)) {
|
||||
mlx5_ib_dbg(dev, "invalid QP state transition from %d to %d, qp_type %d, attr_mask 0x%x\n",
|
||||
cur_state, new_state, ibqp->qp_type, attr_mask);
|
||||
|
@ -4481,9 +4518,14 @@ int mlx5_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
|
|||
return mlx5_ib_gsi_query_qp(ibqp, qp_attr, qp_attr_mask,
|
||||
qp_init_attr);
|
||||
|
||||
/* Not all of output fields are applicable, make sure to zero them */
|
||||
memset(qp_init_attr, 0, sizeof(*qp_init_attr));
|
||||
memset(qp_attr, 0, sizeof(*qp_attr));
|
||||
|
||||
mutex_lock(&qp->mutex);
|
||||
|
||||
if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET) {
|
||||
if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET ||
|
||||
qp->flags & MLX5_IB_QP_UNDERLAY) {
|
||||
err = query_raw_packet_qp_state(dev, qp, &raw_packet_qp_state);
|
||||
if (err)
|
||||
goto out;
|
||||
|
|
Loading…
Reference in New Issue