Commit 2978975c authored by Leon Romanovsky's avatar Leon Romanovsky Committed by Jason Gunthorpe

RDMA/mlx5: Process create QP flags in one place

create_flags is checked in too many places and scattered across all
the code, consolidate all the checks inside one function, so we will
be easily see the flow. As part of such change, delete unreachable code,
because IB/core is responsible sanitize the input.

Link: https://lore.kernel.org/r/20200427154636.381474-15-leon@kernel.orgReviewed-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 2be08c30
...@@ -1097,17 +1097,9 @@ static int create_kernel_qp(struct mlx5_ib_dev *dev, ...@@ -1097,17 +1097,9 @@ static int create_kernel_qp(struct mlx5_ib_dev *dev,
void *qpc; void *qpc;
int err; int err;
if (init_attr->create_flags & ~(IB_QP_CREATE_INTEGRITY_EN |
IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK |
IB_QP_CREATE_IPOIB_UD_LSO |
IB_QP_CREATE_NETIF_QP |
MLX5_IB_QP_CREATE_SQPN_QP1 |
MLX5_IB_QP_CREATE_WC_TEST))
return -EINVAL;
if (init_attr->qp_type == MLX5_IB_QPT_REG_UMR) if (init_attr->qp_type == MLX5_IB_QPT_REG_UMR)
qp->bf.bfreg = &dev->fp_bfreg; qp->bf.bfreg = &dev->fp_bfreg;
else if (init_attr->create_flags & MLX5_IB_QP_CREATE_WC_TEST) else if (qp->flags & MLX5_IB_QP_CREATE_WC_TEST)
qp->bf.bfreg = &dev->wc_bfreg; qp->bf.bfreg = &dev->wc_bfreg;
else else
qp->bf.bfreg = &dev->bfreg; qp->bf.bfreg = &dev->bfreg;
...@@ -1167,10 +1159,8 @@ static int create_kernel_qp(struct mlx5_ib_dev *dev, ...@@ -1167,10 +1159,8 @@ static int create_kernel_qp(struct mlx5_ib_dev *dev,
MLX5_SET(qpc, qpc, fre, 1); MLX5_SET(qpc, qpc, fre, 1);
MLX5_SET(qpc, qpc, rlky, 1); MLX5_SET(qpc, qpc, rlky, 1);
if (init_attr->create_flags & MLX5_IB_QP_CREATE_SQPN_QP1) { if (qp->flags & MLX5_IB_QP_CREATE_SQPN_QP1)
MLX5_SET(qpc, qpc, deth_sqpn, 1); MLX5_SET(qpc, qpc, deth_sqpn, 1);
qp->flags |= MLX5_IB_QP_CREATE_SQPN_QP1;
}
mlx5_fill_page_frag_array(&qp->buf, mlx5_fill_page_frag_array(&qp->buf,
(__be64 *)MLX5_ADDR_OF(create_qp_in, (__be64 *)MLX5_ADDR_OF(create_qp_in,
...@@ -1657,7 +1647,7 @@ static int create_rss_raw_qp_tir(struct ib_pd *pd, struct mlx5_ib_qp *qp, ...@@ -1657,7 +1647,7 @@ static int create_rss_raw_qp_tir(struct ib_pd *pd, struct mlx5_ib_qp *qp,
size_t required_cmd_sz; size_t required_cmd_sz;
u8 lb_flag = 0; u8 lb_flag = 0;
if (init_attr->create_flags || init_attr->send_cq) if (init_attr->send_cq)
return -EINVAL; return -EINVAL;
min_resp_len = offsetof(typeof(resp), bfreg_index) + sizeof(resp.bfreg_index); min_resp_len = offsetof(typeof(resp), bfreg_index) + sizeof(resp.bfreg_index);
...@@ -1996,62 +1986,9 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd, ...@@ -1996,62 +1986,9 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
if (mlx5_st < 0) if (mlx5_st < 0)
return -EINVAL; return -EINVAL;
if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) {
if (!MLX5_CAP_GEN(mdev, block_lb_mc)) {
mlx5_ib_dbg(dev, "block multicast loopback isn't supported\n");
return -EINVAL;
} else {
qp->flags |= IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK;
}
}
if (init_attr->create_flags &
(IB_QP_CREATE_CROSS_CHANNEL |
IB_QP_CREATE_MANAGED_SEND |
IB_QP_CREATE_MANAGED_RECV)) {
if (!MLX5_CAP_GEN(mdev, cd)) {
mlx5_ib_dbg(dev, "cross-channel isn't supported\n");
return -EINVAL;
}
if (init_attr->create_flags & IB_QP_CREATE_CROSS_CHANNEL)
qp->flags |= IB_QP_CREATE_CROSS_CHANNEL;
if (init_attr->create_flags & IB_QP_CREATE_MANAGED_SEND)
qp->flags |= IB_QP_CREATE_MANAGED_SEND;
if (init_attr->create_flags & IB_QP_CREATE_MANAGED_RECV)
qp->flags |= IB_QP_CREATE_MANAGED_RECV;
}
if (init_attr->qp_type == IB_QPT_UD &&
(init_attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO))
if (!MLX5_CAP_GEN(mdev, ipoib_basic_offloads)) {
mlx5_ib_dbg(dev, "ipoib UD lso qp isn't supported\n");
return -EOPNOTSUPP;
}
if (init_attr->create_flags & IB_QP_CREATE_SCATTER_FCS) {
if (init_attr->qp_type != IB_QPT_RAW_PACKET) {
mlx5_ib_dbg(dev, "Scatter FCS is supported only for Raw Packet QPs");
return -EOPNOTSUPP;
}
if (!MLX5_CAP_GEN(dev->mdev, eth_net_offloads) ||
!MLX5_CAP_ETH(dev->mdev, scatter_fcs)) {
mlx5_ib_dbg(dev, "Scatter FCS isn't supported\n");
return -EOPNOTSUPP;
}
qp->flags |= IB_QP_CREATE_SCATTER_FCS;
}
if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
qp->sq_signal_bits = MLX5_WQE_CTRL_CQ_UPDATE; qp->sq_signal_bits = MLX5_WQE_CTRL_CQ_UPDATE;
if (init_attr->create_flags & IB_QP_CREATE_CVLAN_STRIPPING) {
if (!(MLX5_CAP_GEN(dev->mdev, eth_net_offloads) &&
MLX5_CAP_ETH(dev->mdev, vlan_cap)) ||
(init_attr->qp_type != IB_QPT_RAW_PACKET))
return -EOPNOTSUPP;
qp->flags |= IB_QP_CREATE_CVLAN_STRIPPING;
}
if (udata) { if (udata) {
if (!check_flags_mask(ucmd->flags, if (!check_flags_mask(ucmd->flags,
MLX5_QP_FLAG_ALLOW_SCATTER_CQE | MLX5_QP_FLAG_ALLOW_SCATTER_CQE |
...@@ -2108,23 +2045,13 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd, ...@@ -2108,23 +2045,13 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
} }
qp->flags_en |= MLX5_QP_FLAG_PACKET_BASED_CREDIT_MODE; qp->flags_en |= MLX5_QP_FLAG_PACKET_BASED_CREDIT_MODE;
} }
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 |= IB_QP_CREATE_SOURCE_QPN;
qp->underlay_qpn = init_attr->source_qpn;
}
} else { } else {
qp->wq_sig = !!wq_signature; qp->wq_sig = !!wq_signature;
} }
if (qp->flags & IB_QP_CREATE_SOURCE_QPN)
qp->underlay_qpn = init_attr->source_qpn;
base = (init_attr->qp_type == IB_QPT_RAW_PACKET || base = (init_attr->qp_type == IB_QPT_RAW_PACKET ||
qp->flags & IB_QP_CREATE_SOURCE_QPN) ? qp->flags & IB_QP_CREATE_SOURCE_QPN) ?
&qp->raw_packet_qp.rq.base : &qp->raw_packet_qp.rq.base :
...@@ -2153,11 +2080,6 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd, ...@@ -2153,11 +2080,6 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
ucmd->sq_wqe_count, max_wqes); ucmd->sq_wqe_count, max_wqes);
return -EINVAL; return -EINVAL;
} }
if (init_attr->create_flags &
MLX5_IB_QP_CREATE_SQPN_QP1) {
mlx5_ib_dbg(dev, "user-space is not allowed to create UD QPs spoofing as QP1\n");
return -EINVAL;
}
err = create_user_qp(dev, pd, qp, udata, init_attr, &in, err = create_user_qp(dev, pd, qp, udata, init_attr, &in,
&resp, &inlen, base); &resp, &inlen, base);
if (err) if (err)
...@@ -2273,23 +2195,15 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd, ...@@ -2273,23 +2195,15 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
MLX5_SET(qpc, qpc, user_index, uidx); MLX5_SET(qpc, qpc, user_index, uidx);
/* we use IB_QP_CREATE_IPOIB_UD_LSO to indicates ipoib qp */ /* we use IB_QP_CREATE_IPOIB_UD_LSO to indicates ipoib qp */
if (init_attr->qp_type == IB_QPT_UD && if (qp->flags & IB_QP_CREATE_IPOIB_UD_LSO)
(init_attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO)) {
MLX5_SET(qpc, qpc, ulp_stateless_offload_mode, 1); MLX5_SET(qpc, qpc, ulp_stateless_offload_mode, 1);
qp->flags |= IB_QP_CREATE_IPOIB_UD_LSO;
}
if (init_attr->create_flags & IB_QP_CREATE_PCI_WRITE_END_PADDING) { if (qp->flags & IB_QP_CREATE_PCI_WRITE_END_PADDING &&
if (!MLX5_CAP_GEN(dev->mdev, end_pad)) { init_attr->qp_type != IB_QPT_RAW_PACKET) {
mlx5_ib_dbg(dev, "scatter end padding is not supported\n"); MLX5_SET(qpc, qpc, end_padding_mode,
err = -EOPNOTSUPP; MLX5_WQ_END_PAD_MODE_ALIGN);
goto err; /* Special case to clean flag */
} else if (init_attr->qp_type != IB_QPT_RAW_PACKET) { qp->flags &= ~IB_QP_CREATE_PCI_WRITE_END_PADDING;
MLX5_SET(qpc, qpc, end_padding_mode,
MLX5_WQ_END_PAD_MODE_ALIGN);
} else {
qp->flags |= IB_QP_CREATE_PCI_WRITE_END_PADDING;
}
} }
if (inlen < 0) { if (inlen < 0) {
...@@ -2670,6 +2584,91 @@ static int process_vendor_flags(struct mlx5_ib_qp *qp, ...@@ -2670,6 +2584,91 @@ static int process_vendor_flags(struct mlx5_ib_qp *qp,
return 0; return 0;
} }
static void process_create_flag(struct mlx5_ib_dev *dev, int *flags, int flag,
bool cond, struct mlx5_ib_qp *qp)
{
if (!(*flags & flag))
return;
if (cond) {
qp->flags |= flag;
*flags &= ~flag;
return;
}
if (flag == MLX5_IB_QP_CREATE_WC_TEST) {
/*
* Special case, if condition didn't meet, it won't be error,
* just different in-kernel flow.
*/
*flags &= ~MLX5_IB_QP_CREATE_WC_TEST;
return;
}
mlx5_ib_dbg(dev, "Verbs create QP flag 0x%X is not supported\n", flag);
}
static int process_create_flags(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
struct ib_qp_init_attr *attr)
{
enum ib_qp_type qp_type = attr->qp_type;
struct mlx5_core_dev *mdev = dev->mdev;
int create_flags = attr->create_flags;
bool cond;
if (qp->qp_sub_type == MLX5_IB_QPT_DCT)
return (create_flags) ? -EINVAL : 0;
if (qp_type == IB_QPT_RAW_PACKET && attr->rwq_ind_tbl)
return (create_flags) ? -EINVAL : 0;
process_create_flag(dev, &create_flags,
IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK,
MLX5_CAP_GEN(mdev, block_lb_mc), qp);
process_create_flag(dev, &create_flags, IB_QP_CREATE_CROSS_CHANNEL,
MLX5_CAP_GEN(mdev, cd), qp);
process_create_flag(dev, &create_flags, IB_QP_CREATE_MANAGED_SEND,
MLX5_CAP_GEN(mdev, cd), qp);
process_create_flag(dev, &create_flags, IB_QP_CREATE_MANAGED_RECV,
MLX5_CAP_GEN(mdev, cd), qp);
if (qp_type == IB_QPT_UD) {
process_create_flag(dev, &create_flags,
IB_QP_CREATE_IPOIB_UD_LSO,
MLX5_CAP_GEN(mdev, ipoib_basic_offloads),
qp);
cond = MLX5_CAP_GEN(mdev, port_type) == MLX5_CAP_PORT_TYPE_IB;
process_create_flag(dev, &create_flags, IB_QP_CREATE_SOURCE_QPN,
cond, qp);
}
if (qp_type == IB_QPT_RAW_PACKET) {
cond = MLX5_CAP_GEN(mdev, eth_net_offloads) &&
MLX5_CAP_ETH(mdev, scatter_fcs);
process_create_flag(dev, &create_flags,
IB_QP_CREATE_SCATTER_FCS, cond, qp);
cond = MLX5_CAP_GEN(mdev, eth_net_offloads) &&
MLX5_CAP_ETH(mdev, vlan_cap);
process_create_flag(dev, &create_flags,
IB_QP_CREATE_CVLAN_STRIPPING, cond, qp);
}
process_create_flag(dev, &create_flags,
IB_QP_CREATE_PCI_WRITE_END_PADDING,
MLX5_CAP_GEN(mdev, end_pad), qp);
process_create_flag(dev, &create_flags, MLX5_IB_QP_CREATE_WC_TEST,
qp_type != MLX5_IB_QPT_REG_UMR, qp);
process_create_flag(dev, &create_flags, MLX5_IB_QP_CREATE_SQPN_QP1,
true, qp);
if (create_flags)
mlx5_ib_dbg(dev, "Create QP has unsupported flags 0x%X\n",
create_flags);
return (create_flags) ? -EINVAL : 0;
}
static int create_driver_qp(struct ib_pd *pd, struct mlx5_ib_qp *qp, static int create_driver_qp(struct ib_pd *pd, struct mlx5_ib_qp *qp,
struct ib_qp_init_attr *attr, struct ib_qp_init_attr *attr,
struct mlx5_ib_create_qp *ucmd, struct mlx5_ib_create_qp *ucmd,
...@@ -2769,6 +2768,9 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, ...@@ -2769,6 +2768,9 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd,
if (err) if (err)
goto free_qp; goto free_qp;
} }
err = process_create_flags(dev, qp, init_attr);
if (err)
goto free_qp;
if (init_attr->qp_type == IB_QPT_XRC_TGT) if (init_attr->qp_type == IB_QPT_XRC_TGT)
xrcdn = to_mxrcd(init_attr->xrcd)->xrcdn; xrcdn = to_mxrcd(init_attr->xrcd)->xrcdn;
......
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