112515907SHans Petter Selasky /*-
24fb0a74eSHans Petter Selasky * Copyright (c) 2013-2021, Mellanox Technologies. All rights reserved.
312515907SHans Petter Selasky *
412515907SHans Petter Selasky * Redistribution and use in source and binary forms, with or without
512515907SHans Petter Selasky * modification, are permitted provided that the following conditions
612515907SHans Petter Selasky * are met:
712515907SHans Petter Selasky * 1. Redistributions of source code must retain the above copyright
812515907SHans Petter Selasky * notice, this list of conditions and the following disclaimer.
912515907SHans Petter Selasky * 2. Redistributions in binary form must reproduce the above copyright
1012515907SHans Petter Selasky * notice, this list of conditions and the following disclaimer in the
1112515907SHans Petter Selasky * documentation and/or other materials provided with the distribution.
1212515907SHans Petter Selasky *
1312515907SHans Petter Selasky * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
1412515907SHans Petter Selasky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1512515907SHans Petter Selasky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1612515907SHans Petter Selasky * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
1712515907SHans Petter Selasky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1812515907SHans Petter Selasky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1912515907SHans Petter Selasky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2012515907SHans Petter Selasky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2112515907SHans Petter Selasky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2212515907SHans Petter Selasky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2312515907SHans Petter Selasky * SUCH DAMAGE.
2412515907SHans Petter Selasky */
2512515907SHans Petter Selasky
2670600979SKonstantin Belousov #include "opt_rss.h"
2770600979SKonstantin Belousov #include "opt_ratelimit.h"
2870600979SKonstantin Belousov
2912515907SHans Petter Selasky #include <linux/module.h>
3012515907SHans Petter Selasky #include <rdma/ib_umem.h>
318e6e287fSHans Petter Selasky #include <rdma/ib_cache.h>
328e6e287fSHans Petter Selasky #include <rdma/ib_user_verbs.h>
33b633e08cSHans Petter Selasky #include <rdma/uverbs_ioctl.h>
34*028130b8SKonstantin Belousov #include <dev/mlx5/mlx5_ib/mlx5_ib.h>
3512515907SHans Petter Selasky
3612515907SHans Petter Selasky /* not supported currently */
378e6e287fSHans Petter Selasky static int wq_signature;
3812515907SHans Petter Selasky
3912515907SHans Petter Selasky enum {
4012515907SHans Petter Selasky MLX5_IB_ACK_REQ_FREQ = 8,
4112515907SHans Petter Selasky };
4212515907SHans Petter Selasky
4312515907SHans Petter Selasky enum {
4412515907SHans Petter Selasky MLX5_IB_DEFAULT_SCHED_QUEUE = 0x83,
4512515907SHans Petter Selasky MLX5_IB_DEFAULT_QP0_SCHED_QUEUE = 0x3f,
4612515907SHans Petter Selasky MLX5_IB_LINK_TYPE_IB = 0,
4712515907SHans Petter Selasky MLX5_IB_LINK_TYPE_ETH = 1
4812515907SHans Petter Selasky };
4912515907SHans Petter Selasky
5012515907SHans Petter Selasky enum {
5112515907SHans Petter Selasky MLX5_IB_SQ_STRIDE = 6,
5212515907SHans Petter Selasky };
5312515907SHans Petter Selasky
5412515907SHans Petter Selasky static const u32 mlx5_ib_opcode[] = {
5512515907SHans Petter Selasky [IB_WR_SEND] = MLX5_OPCODE_SEND,
568e6e287fSHans Petter Selasky [IB_WR_LSO] = MLX5_OPCODE_LSO,
5712515907SHans Petter Selasky [IB_WR_SEND_WITH_IMM] = MLX5_OPCODE_SEND_IMM,
5812515907SHans Petter Selasky [IB_WR_RDMA_WRITE] = MLX5_OPCODE_RDMA_WRITE,
5912515907SHans Petter Selasky [IB_WR_RDMA_WRITE_WITH_IMM] = MLX5_OPCODE_RDMA_WRITE_IMM,
6012515907SHans Petter Selasky [IB_WR_RDMA_READ] = MLX5_OPCODE_RDMA_READ,
6112515907SHans Petter Selasky [IB_WR_ATOMIC_CMP_AND_SWP] = MLX5_OPCODE_ATOMIC_CS,
6212515907SHans Petter Selasky [IB_WR_ATOMIC_FETCH_AND_ADD] = MLX5_OPCODE_ATOMIC_FA,
6312515907SHans Petter Selasky [IB_WR_SEND_WITH_INV] = MLX5_OPCODE_SEND_INVAL,
6412515907SHans Petter Selasky [IB_WR_LOCAL_INV] = MLX5_OPCODE_UMR,
658e6e287fSHans Petter Selasky [IB_WR_REG_MR] = MLX5_OPCODE_UMR,
6612515907SHans Petter Selasky [IB_WR_MASKED_ATOMIC_CMP_AND_SWP] = MLX5_OPCODE_ATOMIC_MASKED_CS,
6712515907SHans Petter Selasky [IB_WR_MASKED_ATOMIC_FETCH_AND_ADD] = MLX5_OPCODE_ATOMIC_MASKED_FA,
688e6e287fSHans Petter Selasky [MLX5_IB_WR_UMR] = MLX5_OPCODE_UMR,
6912515907SHans Petter Selasky };
7012515907SHans Petter Selasky
718e6e287fSHans Petter Selasky struct mlx5_wqe_eth_pad {
728e6e287fSHans Petter Selasky u8 rsvd0[16];
7312515907SHans Petter Selasky };
7412515907SHans Petter Selasky
758e6e287fSHans Petter Selasky enum raw_qp_set_mask_map {
768e6e287fSHans Petter Selasky MLX5_RAW_QP_MOD_SET_RQ_Q_CTR_ID = 1UL << 0,
778e6e287fSHans Petter Selasky };
788e6e287fSHans Petter Selasky
798e6e287fSHans Petter Selasky struct mlx5_modify_raw_qp_param {
808e6e287fSHans Petter Selasky u16 operation;
818e6e287fSHans Petter Selasky
828e6e287fSHans Petter Selasky u32 set_mask; /* raw_qp_set_mask_map */
838e6e287fSHans Petter Selasky u8 rq_q_ctr_id;
848e6e287fSHans Petter Selasky };
858e6e287fSHans Petter Selasky
868e6e287fSHans Petter Selasky static void get_cqs(enum ib_qp_type qp_type,
878e6e287fSHans Petter Selasky struct ib_cq *ib_send_cq, struct ib_cq *ib_recv_cq,
888e6e287fSHans Petter Selasky struct mlx5_ib_cq **send_cq, struct mlx5_ib_cq **recv_cq);
898e6e287fSHans Petter Selasky
is_qp0(enum ib_qp_type qp_type)9012515907SHans Petter Selasky static int is_qp0(enum ib_qp_type qp_type)
9112515907SHans Petter Selasky {
9212515907SHans Petter Selasky return qp_type == IB_QPT_SMI;
9312515907SHans Petter Selasky }
9412515907SHans Petter Selasky
is_sqp(enum ib_qp_type qp_type)9512515907SHans Petter Selasky static int is_sqp(enum ib_qp_type qp_type)
9612515907SHans Petter Selasky {
9712515907SHans Petter Selasky return is_qp0(qp_type) || is_qp1(qp_type);
9812515907SHans Petter Selasky }
9912515907SHans Petter Selasky
get_wqe(struct mlx5_ib_qp * qp,int offset)10012515907SHans Petter Selasky static void *get_wqe(struct mlx5_ib_qp *qp, int offset)
10112515907SHans Petter Selasky {
10212515907SHans Petter Selasky return mlx5_buf_offset(&qp->buf, offset);
10312515907SHans Petter Selasky }
10412515907SHans Petter Selasky
get_recv_wqe(struct mlx5_ib_qp * qp,int n)10512515907SHans Petter Selasky static void *get_recv_wqe(struct mlx5_ib_qp *qp, int n)
10612515907SHans Petter Selasky {
10712515907SHans Petter Selasky return get_wqe(qp, qp->rq.offset + (n << qp->rq.wqe_shift));
10812515907SHans Petter Selasky }
10912515907SHans Petter Selasky
mlx5_get_send_wqe(struct mlx5_ib_qp * qp,int n)11012515907SHans Petter Selasky void *mlx5_get_send_wqe(struct mlx5_ib_qp *qp, int n)
11112515907SHans Petter Selasky {
11212515907SHans Petter Selasky return get_wqe(qp, qp->sq.offset + (n << MLX5_IB_SQ_STRIDE));
11312515907SHans Petter Selasky }
11412515907SHans Petter Selasky
1158e6e287fSHans Petter Selasky /**
1168e6e287fSHans Petter Selasky * mlx5_ib_read_user_wqe() - Copy a user-space WQE to kernel space.
1178e6e287fSHans Petter Selasky *
1188e6e287fSHans Petter Selasky * @qp: QP to copy from.
1198e6e287fSHans Petter Selasky * @send: copy from the send queue when non-zero, use the receive queue
1208e6e287fSHans Petter Selasky * otherwise.
1218e6e287fSHans Petter Selasky * @wqe_index: index to start copying from. For send work queues, the
1228e6e287fSHans Petter Selasky * wqe_index is in units of MLX5_SEND_WQE_BB.
1238e6e287fSHans Petter Selasky * For receive work queue, it is the number of work queue
1248e6e287fSHans Petter Selasky * element in the queue.
1258e6e287fSHans Petter Selasky * @buffer: destination buffer.
1268e6e287fSHans Petter Selasky * @length: maximum number of bytes to copy.
1278e6e287fSHans Petter Selasky *
1288e6e287fSHans Petter Selasky * Copies at least a single WQE, but may copy more data.
1298e6e287fSHans Petter Selasky *
1308e6e287fSHans Petter Selasky * Return: the number of bytes copied, or an error code.
1318e6e287fSHans Petter Selasky */
mlx5_ib_read_user_wqe(struct mlx5_ib_qp * qp,int send,int wqe_index,void * buffer,u32 length,struct mlx5_ib_qp_base * base)1328e6e287fSHans Petter Selasky int mlx5_ib_read_user_wqe(struct mlx5_ib_qp *qp, int send, int wqe_index,
1338e6e287fSHans Petter Selasky void *buffer, u32 length,
1348e6e287fSHans Petter Selasky struct mlx5_ib_qp_base *base)
13512515907SHans Petter Selasky {
1368e6e287fSHans Petter Selasky struct ib_device *ibdev = qp->ibqp.device;
1378e6e287fSHans Petter Selasky struct mlx5_ib_dev *dev = to_mdev(ibdev);
1388e6e287fSHans Petter Selasky struct mlx5_ib_wq *wq = send ? &qp->sq : &qp->rq;
1398e6e287fSHans Petter Selasky size_t offset;
1408e6e287fSHans Petter Selasky size_t wq_end;
1418e6e287fSHans Petter Selasky struct ib_umem *umem = base->ubuffer.umem;
1428e6e287fSHans Petter Selasky u32 first_copy_length;
1438e6e287fSHans Petter Selasky int wqe_length;
14412515907SHans Petter Selasky int ret;
14512515907SHans Petter Selasky
1468e6e287fSHans Petter Selasky if (wq->wqe_cnt == 0) {
1478e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "mlx5_ib_read_user_wqe for a QP with wqe_cnt == 0. qp_type: 0x%x\n",
1488e6e287fSHans Petter Selasky qp->ibqp.qp_type);
1498e6e287fSHans Petter Selasky return -EINVAL;
1508e6e287fSHans Petter Selasky }
15112515907SHans Petter Selasky
1528e6e287fSHans Petter Selasky offset = wq->offset + ((wqe_index % wq->wqe_cnt) << wq->wqe_shift);
1538e6e287fSHans Petter Selasky wq_end = wq->offset + (wq->wqe_cnt << wq->wqe_shift);
15412515907SHans Petter Selasky
1558e6e287fSHans Petter Selasky if (send && length < sizeof(struct mlx5_wqe_ctrl_seg))
1568e6e287fSHans Petter Selasky return -EINVAL;
1578e6e287fSHans Petter Selasky
1588e6e287fSHans Petter Selasky if (offset > umem->length ||
1598e6e287fSHans Petter Selasky (send && offset + sizeof(struct mlx5_wqe_ctrl_seg) > umem->length))
1608e6e287fSHans Petter Selasky return -EINVAL;
1618e6e287fSHans Petter Selasky
1628e6e287fSHans Petter Selasky first_copy_length = min_t(u32, offset + length, wq_end) - offset;
1638e6e287fSHans Petter Selasky ret = ib_umem_copy_from(buffer, umem, offset, first_copy_length);
16412515907SHans Petter Selasky if (ret)
16512515907SHans Petter Selasky return ret;
1668e6e287fSHans Petter Selasky
1678e6e287fSHans Petter Selasky if (send) {
1688e6e287fSHans Petter Selasky struct mlx5_wqe_ctrl_seg *ctrl = buffer;
1698e6e287fSHans Petter Selasky int ds = be32_to_cpu(ctrl->qpn_ds) & MLX5_WQE_CTRL_DS_MASK;
1708e6e287fSHans Petter Selasky
1718e6e287fSHans Petter Selasky wqe_length = ds * MLX5_WQE_DS_UNITS;
1728e6e287fSHans Petter Selasky } else {
1738e6e287fSHans Petter Selasky wqe_length = 1 << wq->wqe_shift;
17412515907SHans Petter Selasky }
17512515907SHans Petter Selasky
1768e6e287fSHans Petter Selasky if (wqe_length <= first_copy_length)
1778e6e287fSHans Petter Selasky return first_copy_length;
17812515907SHans Petter Selasky
1798e6e287fSHans Petter Selasky ret = ib_umem_copy_from(buffer + first_copy_length, umem, wq->offset,
1808e6e287fSHans Petter Selasky wqe_length - first_copy_length);
1818e6e287fSHans Petter Selasky if (ret)
1828e6e287fSHans Petter Selasky return ret;
18312515907SHans Petter Selasky
1848e6e287fSHans Petter Selasky return wqe_length;
18512515907SHans Petter Selasky }
18612515907SHans Petter Selasky
mlx5_ib_qp_event(struct mlx5_core_qp * qp,int type)18712515907SHans Petter Selasky static void mlx5_ib_qp_event(struct mlx5_core_qp *qp, int type)
18812515907SHans Petter Selasky {
18912515907SHans Petter Selasky struct ib_qp *ibqp = &to_mibqp(qp)->ibqp;
19012515907SHans Petter Selasky struct ib_event event;
19112515907SHans Petter Selasky
1928e6e287fSHans Petter Selasky if (type == MLX5_EVENT_TYPE_PATH_MIG) {
1938e6e287fSHans Petter Selasky /* This event is only valid for trans_qps */
1948e6e287fSHans Petter Selasky to_mibqp(qp)->port = to_mibqp(qp)->trans_qp.alt_port;
19512515907SHans Petter Selasky }
19612515907SHans Petter Selasky
19712515907SHans Petter Selasky if (ibqp->event_handler) {
19812515907SHans Petter Selasky event.device = ibqp->device;
19912515907SHans Petter Selasky event.element.qp = ibqp;
20012515907SHans Petter Selasky switch (type) {
20112515907SHans Petter Selasky case MLX5_EVENT_TYPE_PATH_MIG:
20212515907SHans Petter Selasky event.event = IB_EVENT_PATH_MIG;
20312515907SHans Petter Selasky break;
20412515907SHans Petter Selasky case MLX5_EVENT_TYPE_COMM_EST:
20512515907SHans Petter Selasky event.event = IB_EVENT_COMM_EST;
20612515907SHans Petter Selasky break;
20712515907SHans Petter Selasky case MLX5_EVENT_TYPE_SQ_DRAINED:
20812515907SHans Petter Selasky event.event = IB_EVENT_SQ_DRAINED;
20912515907SHans Petter Selasky break;
21012515907SHans Petter Selasky case MLX5_EVENT_TYPE_SRQ_LAST_WQE:
21112515907SHans Petter Selasky event.event = IB_EVENT_QP_LAST_WQE_REACHED;
21212515907SHans Petter Selasky break;
21312515907SHans Petter Selasky case MLX5_EVENT_TYPE_WQ_CATAS_ERROR:
21412515907SHans Petter Selasky event.event = IB_EVENT_QP_FATAL;
21512515907SHans Petter Selasky break;
21612515907SHans Petter Selasky case MLX5_EVENT_TYPE_PATH_MIG_FAILED:
21712515907SHans Petter Selasky event.event = IB_EVENT_PATH_MIG_ERR;
21812515907SHans Petter Selasky break;
21912515907SHans Petter Selasky case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR:
22012515907SHans Petter Selasky event.event = IB_EVENT_QP_REQ_ERR;
22112515907SHans Petter Selasky break;
22212515907SHans Petter Selasky case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR:
22312515907SHans Petter Selasky event.event = IB_EVENT_QP_ACCESS_ERR;
22412515907SHans Petter Selasky break;
22512515907SHans Petter Selasky default:
2268e6e287fSHans Petter Selasky pr_warn("mlx5_ib: Unexpected event type %d on QP %06x\n", type, qp->qpn);
22712515907SHans Petter Selasky return;
22812515907SHans Petter Selasky }
22912515907SHans Petter Selasky
23012515907SHans Petter Selasky ibqp->event_handler(&event, ibqp->qp_context);
23112515907SHans Petter Selasky }
23212515907SHans Petter Selasky }
23312515907SHans Petter Selasky
set_rq_size(struct mlx5_ib_dev * dev,struct ib_qp_cap * cap,int has_rq,struct mlx5_ib_qp * qp,struct mlx5_ib_create_qp * ucmd)23412515907SHans Petter Selasky static int set_rq_size(struct mlx5_ib_dev *dev, struct ib_qp_cap *cap,
23512515907SHans Petter Selasky int has_rq, struct mlx5_ib_qp *qp, struct mlx5_ib_create_qp *ucmd)
23612515907SHans Petter Selasky {
23712515907SHans Petter Selasky int wqe_size;
23812515907SHans Petter Selasky int wq_size;
23912515907SHans Petter Selasky
24012515907SHans Petter Selasky /* Sanity check RQ size before proceeding */
24112515907SHans Petter Selasky if (cap->max_recv_wr > (1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz)))
24212515907SHans Petter Selasky return -EINVAL;
24312515907SHans Petter Selasky
24412515907SHans Petter Selasky if (!has_rq) {
24512515907SHans Petter Selasky qp->rq.max_gs = 0;
24612515907SHans Petter Selasky qp->rq.wqe_cnt = 0;
24712515907SHans Petter Selasky qp->rq.wqe_shift = 0;
24812515907SHans Petter Selasky cap->max_recv_wr = 0;
24912515907SHans Petter Selasky cap->max_recv_sge = 0;
25012515907SHans Petter Selasky } else {
25112515907SHans Petter Selasky if (ucmd) {
25212515907SHans Petter Selasky qp->rq.wqe_cnt = ucmd->rq_wqe_count;
25312515907SHans Petter Selasky qp->rq.wqe_shift = ucmd->rq_wqe_shift;
25412515907SHans Petter Selasky qp->rq.max_gs = (1 << qp->rq.wqe_shift) / sizeof(struct mlx5_wqe_data_seg) - qp->wq_sig;
25512515907SHans Petter Selasky qp->rq.max_post = qp->rq.wqe_cnt;
25612515907SHans Petter Selasky } else {
25712515907SHans Petter Selasky wqe_size = qp->wq_sig ? sizeof(struct mlx5_wqe_signature_seg) : 0;
25812515907SHans Petter Selasky wqe_size += cap->max_recv_sge * sizeof(struct mlx5_wqe_data_seg);
25912515907SHans Petter Selasky wqe_size = roundup_pow_of_two(wqe_size);
26012515907SHans Petter Selasky wq_size = roundup_pow_of_two(cap->max_recv_wr) * wqe_size;
26112515907SHans Petter Selasky wq_size = max_t(int, wq_size, MLX5_SEND_WQE_BB);
26212515907SHans Petter Selasky qp->rq.wqe_cnt = wq_size / wqe_size;
26312515907SHans Petter Selasky if (wqe_size > MLX5_CAP_GEN(dev->mdev, max_wqe_sz_rq)) {
26412515907SHans Petter Selasky mlx5_ib_dbg(dev, "wqe_size %d, max %d\n",
26512515907SHans Petter Selasky wqe_size,
26612515907SHans Petter Selasky MLX5_CAP_GEN(dev->mdev,
26712515907SHans Petter Selasky max_wqe_sz_rq));
26812515907SHans Petter Selasky return -EINVAL;
26912515907SHans Petter Selasky }
27012515907SHans Petter Selasky qp->rq.wqe_shift = ilog2(wqe_size);
27112515907SHans Petter Selasky qp->rq.max_gs = (1 << qp->rq.wqe_shift) / sizeof(struct mlx5_wqe_data_seg) - qp->wq_sig;
27212515907SHans Petter Selasky qp->rq.max_post = qp->rq.wqe_cnt;
27312515907SHans Petter Selasky }
27412515907SHans Petter Selasky }
27512515907SHans Petter Selasky
27612515907SHans Petter Selasky return 0;
27712515907SHans Petter Selasky }
27812515907SHans Petter Selasky
sq_overhead(struct ib_qp_init_attr * attr)2798e6e287fSHans Petter Selasky static int sq_overhead(struct ib_qp_init_attr *attr)
28012515907SHans Petter Selasky {
28112515907SHans Petter Selasky int size = 0;
28212515907SHans Petter Selasky
2838e6e287fSHans Petter Selasky switch (attr->qp_type) {
28412515907SHans Petter Selasky case IB_QPT_XRC_INI:
28512515907SHans Petter Selasky size += sizeof(struct mlx5_wqe_xrc_seg);
28612515907SHans Petter Selasky /* fall through */
28712515907SHans Petter Selasky case IB_QPT_RC:
28812515907SHans Petter Selasky size += sizeof(struct mlx5_wqe_ctrl_seg) +
2898e6e287fSHans Petter Selasky max(sizeof(struct mlx5_wqe_atomic_seg) +
2908e6e287fSHans Petter Selasky sizeof(struct mlx5_wqe_raddr_seg),
29112515907SHans Petter Selasky sizeof(struct mlx5_wqe_umr_ctrl_seg) +
2928e6e287fSHans Petter Selasky sizeof(struct mlx5_mkey_seg));
29312515907SHans Petter Selasky break;
29412515907SHans Petter Selasky
29512515907SHans Petter Selasky case IB_QPT_XRC_TGT:
29612515907SHans Petter Selasky return 0;
29712515907SHans Petter Selasky
29812515907SHans Petter Selasky case IB_QPT_UC:
29912515907SHans Petter Selasky size += sizeof(struct mlx5_wqe_ctrl_seg) +
3008e6e287fSHans Petter Selasky max(sizeof(struct mlx5_wqe_raddr_seg),
30112515907SHans Petter Selasky sizeof(struct mlx5_wqe_umr_ctrl_seg) +
3028e6e287fSHans Petter Selasky sizeof(struct mlx5_mkey_seg));
30312515907SHans Petter Selasky break;
30412515907SHans Petter Selasky
30512515907SHans Petter Selasky case IB_QPT_UD:
3068e6e287fSHans Petter Selasky if (attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO)
3078e6e287fSHans Petter Selasky size += sizeof(struct mlx5_wqe_eth_pad) +
3088e6e287fSHans Petter Selasky sizeof(struct mlx5_wqe_eth_seg);
3098e6e287fSHans Petter Selasky /* fall through */
31012515907SHans Petter Selasky case IB_QPT_SMI:
3118e6e287fSHans Petter Selasky case MLX5_IB_QPT_HW_GSI:
31212515907SHans Petter Selasky size += sizeof(struct mlx5_wqe_ctrl_seg) +
31312515907SHans Petter Selasky sizeof(struct mlx5_wqe_datagram_seg);
31412515907SHans Petter Selasky break;
31512515907SHans Petter Selasky
3168e6e287fSHans Petter Selasky case MLX5_IB_QPT_REG_UMR:
3178e6e287fSHans Petter Selasky size += sizeof(struct mlx5_wqe_ctrl_seg) +
3188e6e287fSHans Petter Selasky sizeof(struct mlx5_wqe_umr_ctrl_seg) +
3198e6e287fSHans Petter Selasky sizeof(struct mlx5_mkey_seg);
3208e6e287fSHans Petter Selasky break;
3218e6e287fSHans Petter Selasky
32212515907SHans Petter Selasky default:
32312515907SHans Petter Selasky return -EINVAL;
32412515907SHans Petter Selasky }
32512515907SHans Petter Selasky
32612515907SHans Petter Selasky return size;
32712515907SHans Petter Selasky }
32812515907SHans Petter Selasky
calc_send_wqe(struct ib_qp_init_attr * attr)32912515907SHans Petter Selasky static int calc_send_wqe(struct ib_qp_init_attr *attr)
33012515907SHans Petter Selasky {
33112515907SHans Petter Selasky int inl_size = 0;
33212515907SHans Petter Selasky int size;
33312515907SHans Petter Selasky
3348e6e287fSHans Petter Selasky size = sq_overhead(attr);
33512515907SHans Petter Selasky if (size < 0)
33612515907SHans Petter Selasky return size;
33712515907SHans Petter Selasky
33812515907SHans Petter Selasky if (attr->cap.max_inline_data) {
33912515907SHans Petter Selasky inl_size = size + sizeof(struct mlx5_wqe_inline_seg) +
34012515907SHans Petter Selasky attr->cap.max_inline_data;
34112515907SHans Petter Selasky }
34212515907SHans Petter Selasky
34312515907SHans Petter Selasky size += attr->cap.max_send_sge * sizeof(struct mlx5_wqe_data_seg);
3448e6e287fSHans Petter Selasky if (attr->create_flags & IB_QP_CREATE_SIGNATURE_EN &&
3458e6e287fSHans Petter Selasky ALIGN(max_t(int, inl_size, size), MLX5_SEND_WQE_BB) < MLX5_SIG_WQE_SIZE)
3468e6e287fSHans Petter Selasky return MLX5_SIG_WQE_SIZE;
34712515907SHans Petter Selasky else
3488e6e287fSHans Petter Selasky return ALIGN(max_t(int, inl_size, size), MLX5_SEND_WQE_BB);
34912515907SHans Petter Selasky }
35012515907SHans Petter Selasky
get_send_sge(struct ib_qp_init_attr * attr,int wqe_size)351c788dceaSHans Petter Selasky static int get_send_sge(struct ib_qp_init_attr *attr, int wqe_size)
352c788dceaSHans Petter Selasky {
353c788dceaSHans Petter Selasky int max_sge;
354c788dceaSHans Petter Selasky
355c788dceaSHans Petter Selasky if (attr->qp_type == IB_QPT_RC)
356c788dceaSHans Petter Selasky max_sge = (min_t(int, wqe_size, 512) -
357c788dceaSHans Petter Selasky sizeof(struct mlx5_wqe_ctrl_seg) -
358c788dceaSHans Petter Selasky sizeof(struct mlx5_wqe_raddr_seg)) /
359c788dceaSHans Petter Selasky sizeof(struct mlx5_wqe_data_seg);
360c788dceaSHans Petter Selasky else if (attr->qp_type == IB_QPT_XRC_INI)
361c788dceaSHans Petter Selasky max_sge = (min_t(int, wqe_size, 512) -
362c788dceaSHans Petter Selasky sizeof(struct mlx5_wqe_ctrl_seg) -
363c788dceaSHans Petter Selasky sizeof(struct mlx5_wqe_xrc_seg) -
364c788dceaSHans Petter Selasky sizeof(struct mlx5_wqe_raddr_seg)) /
365c788dceaSHans Petter Selasky sizeof(struct mlx5_wqe_data_seg);
366c788dceaSHans Petter Selasky else
367c788dceaSHans Petter Selasky max_sge = (wqe_size - sq_overhead(attr)) /
368c788dceaSHans Petter Selasky sizeof(struct mlx5_wqe_data_seg);
369c788dceaSHans Petter Selasky
370c788dceaSHans Petter Selasky return min_t(int, max_sge, wqe_size - sq_overhead(attr) /
371c788dceaSHans Petter Selasky sizeof(struct mlx5_wqe_data_seg));
372c788dceaSHans Petter Selasky }
373c788dceaSHans Petter Selasky
calc_sq_size(struct mlx5_ib_dev * dev,struct ib_qp_init_attr * attr,struct mlx5_ib_qp * qp)37412515907SHans Petter Selasky static int calc_sq_size(struct mlx5_ib_dev *dev, struct ib_qp_init_attr *attr,
37512515907SHans Petter Selasky struct mlx5_ib_qp *qp)
37612515907SHans Petter Selasky {
37712515907SHans Petter Selasky int wqe_size;
37812515907SHans Petter Selasky int wq_size;
37912515907SHans Petter Selasky
38012515907SHans Petter Selasky if (!attr->cap.max_send_wr)
38112515907SHans Petter Selasky return 0;
38212515907SHans Petter Selasky
38312515907SHans Petter Selasky wqe_size = calc_send_wqe(attr);
38412515907SHans Petter Selasky mlx5_ib_dbg(dev, "wqe_size %d\n", wqe_size);
38512515907SHans Petter Selasky if (wqe_size < 0)
38612515907SHans Petter Selasky return wqe_size;
38712515907SHans Petter Selasky
38812515907SHans Petter Selasky if (wqe_size > MLX5_CAP_GEN(dev->mdev, max_wqe_sz_sq)) {
3898e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "wqe_size(%d) > max_sq_desc_sz(%d)\n",
39012515907SHans Petter Selasky wqe_size, MLX5_CAP_GEN(dev->mdev, max_wqe_sz_sq));
39112515907SHans Petter Selasky return -EINVAL;
39212515907SHans Petter Selasky }
39312515907SHans Petter Selasky
3948e6e287fSHans Petter Selasky qp->max_inline_data = wqe_size - sq_overhead(attr) -
39512515907SHans Petter Selasky sizeof(struct mlx5_wqe_inline_seg);
39612515907SHans Petter Selasky attr->cap.max_inline_data = qp->max_inline_data;
39712515907SHans Petter Selasky
3988e6e287fSHans Petter Selasky if (attr->create_flags & IB_QP_CREATE_SIGNATURE_EN)
3998e6e287fSHans Petter Selasky qp->signature_en = true;
4008e6e287fSHans Petter Selasky
4018e6e287fSHans Petter Selasky wq_size = roundup_pow_of_two(attr->cap.max_send_wr * wqe_size);
40212515907SHans Petter Selasky qp->sq.wqe_cnt = wq_size / MLX5_SEND_WQE_BB;
40312515907SHans Petter Selasky if (qp->sq.wqe_cnt > (1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz))) {
4048e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "wqe count(%d) exceeds limits(%d)\n",
40512515907SHans Petter Selasky qp->sq.wqe_cnt,
40612515907SHans Petter Selasky 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz));
40712515907SHans Petter Selasky return -ENOMEM;
40812515907SHans Petter Selasky }
40912515907SHans Petter Selasky qp->sq.wqe_shift = ilog2(MLX5_SEND_WQE_BB);
410c788dceaSHans Petter Selasky qp->sq.max_gs = get_send_sge(attr, wqe_size);
411c788dceaSHans Petter Selasky if (qp->sq.max_gs < attr->cap.max_send_sge)
412c788dceaSHans Petter Selasky return -ENOMEM;
413c788dceaSHans Petter Selasky
414c788dceaSHans Petter Selasky attr->cap.max_send_sge = qp->sq.max_gs;
41512515907SHans Petter Selasky qp->sq.max_post = wq_size / wqe_size;
41612515907SHans Petter Selasky attr->cap.max_send_wr = qp->sq.max_post;
41712515907SHans Petter Selasky
41812515907SHans Petter Selasky return wq_size;
41912515907SHans Petter Selasky }
42012515907SHans Petter Selasky
set_user_buf_size(struct mlx5_ib_dev * dev,struct mlx5_ib_qp * qp,struct mlx5_ib_create_qp * ucmd,struct mlx5_ib_qp_base * base,struct ib_qp_init_attr * attr)42112515907SHans Petter Selasky static int set_user_buf_size(struct mlx5_ib_dev *dev,
42212515907SHans Petter Selasky struct mlx5_ib_qp *qp,
42312515907SHans Petter Selasky struct mlx5_ib_create_qp *ucmd,
4248e6e287fSHans Petter Selasky struct mlx5_ib_qp_base *base,
42512515907SHans Petter Selasky struct ib_qp_init_attr *attr)
42612515907SHans Petter Selasky {
42712515907SHans Petter Selasky int desc_sz = 1 << qp->sq.wqe_shift;
42812515907SHans Petter Selasky
42912515907SHans Petter Selasky if (desc_sz > MLX5_CAP_GEN(dev->mdev, max_wqe_sz_sq)) {
43012515907SHans Petter Selasky mlx5_ib_warn(dev, "desc_sz %d, max_sq_desc_sz %d\n",
43112515907SHans Petter Selasky desc_sz, MLX5_CAP_GEN(dev->mdev, max_wqe_sz_sq));
43212515907SHans Petter Selasky return -EINVAL;
43312515907SHans Petter Selasky }
43412515907SHans Petter Selasky
43512515907SHans Petter Selasky if (ucmd->sq_wqe_count && ((1 << ilog2(ucmd->sq_wqe_count)) != ucmd->sq_wqe_count)) {
43612515907SHans Petter Selasky mlx5_ib_warn(dev, "sq_wqe_count %d, sq_wqe_count %d\n",
43712515907SHans Petter Selasky ucmd->sq_wqe_count, ucmd->sq_wqe_count);
43812515907SHans Petter Selasky return -EINVAL;
43912515907SHans Petter Selasky }
44012515907SHans Petter Selasky
44112515907SHans Petter Selasky qp->sq.wqe_cnt = ucmd->sq_wqe_count;
44212515907SHans Petter Selasky
44312515907SHans Petter Selasky if (qp->sq.wqe_cnt > (1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz))) {
44412515907SHans Petter Selasky mlx5_ib_warn(dev, "wqe_cnt %d, max_wqes %d\n",
44512515907SHans Petter Selasky qp->sq.wqe_cnt,
44612515907SHans Petter Selasky 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz));
44712515907SHans Petter Selasky return -EINVAL;
44812515907SHans Petter Selasky }
44912515907SHans Petter Selasky
45012515907SHans Petter Selasky if (attr->qp_type == IB_QPT_RAW_PACKET) {
4518e6e287fSHans Petter Selasky base->ubuffer.buf_size = qp->rq.wqe_cnt << qp->rq.wqe_shift;
4528e6e287fSHans Petter Selasky qp->raw_packet_qp.sq.ubuffer.buf_size = qp->sq.wqe_cnt << 6;
45312515907SHans Petter Selasky } else {
4548e6e287fSHans Petter Selasky base->ubuffer.buf_size = (qp->rq.wqe_cnt << qp->rq.wqe_shift) +
45512515907SHans Petter Selasky (qp->sq.wqe_cnt << 6);
45612515907SHans Petter Selasky }
45712515907SHans Petter Selasky
45812515907SHans Petter Selasky return 0;
45912515907SHans Petter Selasky }
46012515907SHans Petter Selasky
qp_has_rq(struct ib_qp_init_attr * attr)46112515907SHans Petter Selasky static int qp_has_rq(struct ib_qp_init_attr *attr)
46212515907SHans Petter Selasky {
46312515907SHans Petter Selasky if (attr->qp_type == IB_QPT_XRC_INI ||
46412515907SHans Petter Selasky attr->qp_type == IB_QPT_XRC_TGT || attr->srq ||
4658e6e287fSHans Petter Selasky attr->qp_type == MLX5_IB_QPT_REG_UMR ||
46612515907SHans Petter Selasky !attr->cap.max_recv_wr)
46712515907SHans Petter Selasky return 0;
46812515907SHans Petter Selasky
46912515907SHans Petter Selasky return 1;
47012515907SHans Petter Selasky }
47112515907SHans Petter Selasky
472f8f5b459SHans Petter Selasky enum {
473f8f5b459SHans Petter Selasky /* this is the first blue flame register in the array of bfregs assigned
474f8f5b459SHans Petter Selasky * to a processes. Since we do not use it for blue flame but rather
475f8f5b459SHans Petter Selasky * regular 64 bit doorbells, we do not need a lock for maintaiing
476f8f5b459SHans Petter Selasky * "odd/even" order
477f8f5b459SHans Petter Selasky */
478f8f5b459SHans Petter Selasky NUM_NON_BLUE_FLAME_BFREGS = 1,
479f8f5b459SHans Petter Selasky };
480f8f5b459SHans Petter Selasky
max_bfregs(struct mlx5_ib_dev * dev,struct mlx5_bfreg_info * bfregi)481f8f5b459SHans Petter Selasky static int max_bfregs(struct mlx5_ib_dev *dev, struct mlx5_bfreg_info *bfregi)
48212515907SHans Petter Selasky {
483f8f5b459SHans Petter Selasky return get_num_static_uars(dev, bfregi) * MLX5_NON_FP_BFREGS_PER_UAR;
48412515907SHans Petter Selasky }
48512515907SHans Petter Selasky
num_med_bfreg(struct mlx5_ib_dev * dev,struct mlx5_bfreg_info * bfregi)486f8f5b459SHans Petter Selasky static int num_med_bfreg(struct mlx5_ib_dev *dev,
487f8f5b459SHans Petter Selasky struct mlx5_bfreg_info *bfregi)
48812515907SHans Petter Selasky {
48912515907SHans Petter Selasky int n;
49012515907SHans Petter Selasky
491f8f5b459SHans Petter Selasky n = max_bfregs(dev, bfregi) - bfregi->num_low_latency_bfregs -
492f8f5b459SHans Petter Selasky NUM_NON_BLUE_FLAME_BFREGS;
49312515907SHans Petter Selasky
49412515907SHans Petter Selasky return n >= 0 ? n : 0;
49512515907SHans Petter Selasky }
49612515907SHans Petter Selasky
first_med_bfreg(struct mlx5_ib_dev * dev,struct mlx5_bfreg_info * bfregi)497f8f5b459SHans Petter Selasky static int first_med_bfreg(struct mlx5_ib_dev *dev,
498f8f5b459SHans Petter Selasky struct mlx5_bfreg_info *bfregi)
49912515907SHans Petter Selasky {
500f8f5b459SHans Petter Selasky return num_med_bfreg(dev, bfregi) ? 1 : -ENOMEM;
50112515907SHans Petter Selasky }
50212515907SHans Petter Selasky
first_hi_bfreg(struct mlx5_ib_dev * dev,struct mlx5_bfreg_info * bfregi)503f8f5b459SHans Petter Selasky static int first_hi_bfreg(struct mlx5_ib_dev *dev,
504f8f5b459SHans Petter Selasky struct mlx5_bfreg_info *bfregi)
50512515907SHans Petter Selasky {
50612515907SHans Petter Selasky int med;
50712515907SHans Petter Selasky
508f8f5b459SHans Petter Selasky med = num_med_bfreg(dev, bfregi);
509f8f5b459SHans Petter Selasky return ++med;
51012515907SHans Petter Selasky }
51112515907SHans Petter Selasky
alloc_high_class_bfreg(struct mlx5_ib_dev * dev,struct mlx5_bfreg_info * bfregi)512f8f5b459SHans Petter Selasky static int alloc_high_class_bfreg(struct mlx5_ib_dev *dev,
513f8f5b459SHans Petter Selasky struct mlx5_bfreg_info *bfregi)
51412515907SHans Petter Selasky {
51512515907SHans Petter Selasky int i;
51612515907SHans Petter Selasky
517f8f5b459SHans Petter Selasky for (i = first_hi_bfreg(dev, bfregi); i < max_bfregs(dev, bfregi); i++) {
518f8f5b459SHans Petter Selasky if (!bfregi->count[i]) {
519f8f5b459SHans Petter Selasky bfregi->count[i]++;
52012515907SHans Petter Selasky return i;
52112515907SHans Petter Selasky }
52212515907SHans Petter Selasky }
52312515907SHans Petter Selasky
52412515907SHans Petter Selasky return -ENOMEM;
52512515907SHans Petter Selasky }
52612515907SHans Petter Selasky
alloc_med_class_bfreg(struct mlx5_ib_dev * dev,struct mlx5_bfreg_info * bfregi)527f8f5b459SHans Petter Selasky static int alloc_med_class_bfreg(struct mlx5_ib_dev *dev,
528f8f5b459SHans Petter Selasky struct mlx5_bfreg_info *bfregi)
52912515907SHans Petter Selasky {
530f8f5b459SHans Petter Selasky int minidx = first_med_bfreg(dev, bfregi);
53112515907SHans Petter Selasky int i;
53212515907SHans Petter Selasky
533f8f5b459SHans Petter Selasky if (minidx < 0)
534f8f5b459SHans Petter Selasky return minidx;
535f8f5b459SHans Petter Selasky
536f8f5b459SHans Petter Selasky for (i = minidx; i < first_hi_bfreg(dev, bfregi); i++) {
537f8f5b459SHans Petter Selasky if (bfregi->count[i] < bfregi->count[minidx])
53812515907SHans Petter Selasky minidx = i;
539f8f5b459SHans Petter Selasky if (!bfregi->count[minidx])
540f8f5b459SHans Petter Selasky break;
54112515907SHans Petter Selasky }
54212515907SHans Petter Selasky
543f8f5b459SHans Petter Selasky bfregi->count[minidx]++;
54412515907SHans Petter Selasky return minidx;
54512515907SHans Petter Selasky }
54612515907SHans Petter Selasky
alloc_bfreg(struct mlx5_ib_dev * dev,struct mlx5_bfreg_info * bfregi)547f8f5b459SHans Petter Selasky static int alloc_bfreg(struct mlx5_ib_dev *dev,
548f8f5b459SHans Petter Selasky struct mlx5_bfreg_info *bfregi)
54912515907SHans Petter Selasky {
550f8f5b459SHans Petter Selasky int bfregn = -ENOMEM;
55112515907SHans Petter Selasky
552f8f5b459SHans Petter Selasky if (bfregi->lib_uar_dyn)
553f8f5b459SHans Petter Selasky return -EINVAL;
55412515907SHans Petter Selasky
555f8f5b459SHans Petter Selasky mutex_lock(&bfregi->lock);
556f8f5b459SHans Petter Selasky if (bfregi->ver >= 2) {
557f8f5b459SHans Petter Selasky bfregn = alloc_high_class_bfreg(dev, bfregi);
558f8f5b459SHans Petter Selasky if (bfregn < 0)
559f8f5b459SHans Petter Selasky bfregn = alloc_med_class_bfreg(dev, bfregi);
56012515907SHans Petter Selasky }
56112515907SHans Petter Selasky
562f8f5b459SHans Petter Selasky if (bfregn < 0) {
563f8f5b459SHans Petter Selasky BUILD_BUG_ON(NUM_NON_BLUE_FLAME_BFREGS != 1);
564f8f5b459SHans Petter Selasky bfregn = 0;
565f8f5b459SHans Petter Selasky bfregi->count[bfregn]++;
566f8f5b459SHans Petter Selasky }
567f8f5b459SHans Petter Selasky mutex_unlock(&bfregi->lock);
568f8f5b459SHans Petter Selasky
569f8f5b459SHans Petter Selasky return bfregn;
570f8f5b459SHans Petter Selasky }
571f8f5b459SHans Petter Selasky
mlx5_ib_free_bfreg(struct mlx5_ib_dev * dev,struct mlx5_bfreg_info * bfregi,int bfregn)572f8f5b459SHans Petter Selasky void mlx5_ib_free_bfreg(struct mlx5_ib_dev *dev, struct mlx5_bfreg_info *bfregi, int bfregn)
57312515907SHans Petter Selasky {
574f8f5b459SHans Petter Selasky mutex_lock(&bfregi->lock);
575f8f5b459SHans Petter Selasky bfregi->count[bfregn]--;
576f8f5b459SHans Petter Selasky mutex_unlock(&bfregi->lock);
57712515907SHans Petter Selasky }
57812515907SHans Petter Selasky
to_mlx5_state(enum ib_qp_state state)57912515907SHans Petter Selasky static enum mlx5_qp_state to_mlx5_state(enum ib_qp_state state)
58012515907SHans Petter Selasky {
58112515907SHans Petter Selasky switch (state) {
58212515907SHans Petter Selasky case IB_QPS_RESET: return MLX5_QP_STATE_RST;
58312515907SHans Petter Selasky case IB_QPS_INIT: return MLX5_QP_STATE_INIT;
58412515907SHans Petter Selasky case IB_QPS_RTR: return MLX5_QP_STATE_RTR;
58512515907SHans Petter Selasky case IB_QPS_RTS: return MLX5_QP_STATE_RTS;
58612515907SHans Petter Selasky case IB_QPS_SQD: return MLX5_QP_STATE_SQD;
58712515907SHans Petter Selasky case IB_QPS_SQE: return MLX5_QP_STATE_SQER;
58812515907SHans Petter Selasky case IB_QPS_ERR: return MLX5_QP_STATE_ERR;
58912515907SHans Petter Selasky default: return -1;
59012515907SHans Petter Selasky }
59112515907SHans Petter Selasky }
59212515907SHans Petter Selasky
to_mlx5_st(enum ib_qp_type type)59312515907SHans Petter Selasky static int to_mlx5_st(enum ib_qp_type type)
59412515907SHans Petter Selasky {
59512515907SHans Petter Selasky switch (type) {
59612515907SHans Petter Selasky case IB_QPT_RC: return MLX5_QP_ST_RC;
59712515907SHans Petter Selasky case IB_QPT_UC: return MLX5_QP_ST_UC;
59812515907SHans Petter Selasky case IB_QPT_UD: return MLX5_QP_ST_UD;
5998e6e287fSHans Petter Selasky case MLX5_IB_QPT_REG_UMR: return MLX5_QP_ST_REG_UMR;
60012515907SHans Petter Selasky case IB_QPT_XRC_INI:
60112515907SHans Petter Selasky case IB_QPT_XRC_TGT: return MLX5_QP_ST_XRC;
60212515907SHans Petter Selasky case IB_QPT_SMI: return MLX5_QP_ST_QP0;
6038e6e287fSHans Petter Selasky case MLX5_IB_QPT_HW_GSI: return MLX5_QP_ST_QP1;
60412515907SHans Petter Selasky case IB_QPT_RAW_IPV6: return MLX5_QP_ST_RAW_IPV6;
60512515907SHans Petter Selasky case IB_QPT_RAW_PACKET:
60612515907SHans Petter Selasky case IB_QPT_RAW_ETHERTYPE: return MLX5_QP_ST_RAW_ETHERTYPE;
60712515907SHans Petter Selasky case IB_QPT_MAX:
60812515907SHans Petter Selasky default: return -EINVAL;
60912515907SHans Petter Selasky }
61012515907SHans Petter Selasky }
61112515907SHans Petter Selasky
61212515907SHans Petter Selasky static void mlx5_ib_lock_cqs(struct mlx5_ib_cq *send_cq,
61312515907SHans Petter Selasky struct mlx5_ib_cq *recv_cq);
61412515907SHans Petter Selasky static void mlx5_ib_unlock_cqs(struct mlx5_ib_cq *send_cq,
61512515907SHans Petter Selasky struct mlx5_ib_cq *recv_cq);
61612515907SHans Petter Selasky
bfregn_to_uar_index(struct mlx5_ib_dev * dev,struct mlx5_bfreg_info * bfregi,u32 bfregn,bool dyn_bfreg)617f8f5b459SHans Petter Selasky int bfregn_to_uar_index(struct mlx5_ib_dev *dev,
618f8f5b459SHans Petter Selasky struct mlx5_bfreg_info *bfregi, u32 bfregn,
619f8f5b459SHans Petter Selasky bool dyn_bfreg)
62012515907SHans Petter Selasky {
621f8f5b459SHans Petter Selasky unsigned int bfregs_per_sys_page;
622f8f5b459SHans Petter Selasky u32 index_of_sys_page;
623f8f5b459SHans Petter Selasky u32 offset;
624f8f5b459SHans Petter Selasky
625f8f5b459SHans Petter Selasky if (bfregi->lib_uar_dyn)
626f8f5b459SHans Petter Selasky return -EINVAL;
627f8f5b459SHans Petter Selasky
628f8f5b459SHans Petter Selasky bfregs_per_sys_page = get_uars_per_sys_page(dev, bfregi->lib_uar_4k) *
629f8f5b459SHans Petter Selasky MLX5_NON_FP_BFREGS_PER_UAR;
630f8f5b459SHans Petter Selasky index_of_sys_page = bfregn / bfregs_per_sys_page;
631f8f5b459SHans Petter Selasky
632f8f5b459SHans Petter Selasky if (dyn_bfreg) {
633f8f5b459SHans Petter Selasky index_of_sys_page += bfregi->num_static_sys_pages;
634f8f5b459SHans Petter Selasky
635f8f5b459SHans Petter Selasky if (index_of_sys_page >= bfregi->num_sys_pages)
636f8f5b459SHans Petter Selasky return -EINVAL;
637f8f5b459SHans Petter Selasky
638f8f5b459SHans Petter Selasky if (bfregn > bfregi->num_dyn_bfregs ||
639f8f5b459SHans Petter Selasky bfregi->sys_pages[index_of_sys_page] == MLX5_IB_INVALID_UAR_INDEX) {
640f8f5b459SHans Petter Selasky mlx5_ib_dbg(dev, "Invalid dynamic uar index\n");
641f8f5b459SHans Petter Selasky return -EINVAL;
642f8f5b459SHans Petter Selasky }
643f8f5b459SHans Petter Selasky }
644f8f5b459SHans Petter Selasky
645f8f5b459SHans Petter Selasky offset = bfregn % bfregs_per_sys_page / MLX5_NON_FP_BFREGS_PER_UAR;
646f8f5b459SHans Petter Selasky return bfregi->sys_pages[index_of_sys_page] + offset;
64712515907SHans Petter Selasky }
64812515907SHans Petter Selasky
mlx5_ib_umem_get(struct mlx5_ib_dev * dev,struct ib_pd * pd,unsigned long addr,size_t size,struct ib_umem ** umem,int * npages,int * page_shift,int * ncont,u32 * offset)6498e6e287fSHans Petter Selasky static int mlx5_ib_umem_get(struct mlx5_ib_dev *dev,
6508e6e287fSHans Petter Selasky struct ib_pd *pd,
6518e6e287fSHans Petter Selasky unsigned long addr, size_t size,
6528e6e287fSHans Petter Selasky struct ib_umem **umem,
6538e6e287fSHans Petter Selasky int *npages, int *page_shift, int *ncont,
6548e6e287fSHans Petter Selasky u32 *offset)
6558e6e287fSHans Petter Selasky {
6568e6e287fSHans Petter Selasky int err;
6578e6e287fSHans Petter Selasky
6588e6e287fSHans Petter Selasky *umem = ib_umem_get(pd->uobject->context, addr, size, 0, 0);
6598e6e287fSHans Petter Selasky if (IS_ERR(*umem)) {
6608e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "umem_get failed\n");
6618e6e287fSHans Petter Selasky return PTR_ERR(*umem);
6628e6e287fSHans Petter Selasky }
6638e6e287fSHans Petter Selasky
664565cb4e8SHans Petter Selasky mlx5_ib_cont_pages(*umem, addr, 0, npages, page_shift, ncont, NULL);
6658e6e287fSHans Petter Selasky
6668e6e287fSHans Petter Selasky err = mlx5_ib_get_buf_offset(addr, *page_shift, offset);
6678e6e287fSHans Petter Selasky if (err) {
6688e6e287fSHans Petter Selasky mlx5_ib_warn(dev, "bad offset\n");
6698e6e287fSHans Petter Selasky goto err_umem;
6708e6e287fSHans Petter Selasky }
6718e6e287fSHans Petter Selasky
6728e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "addr 0x%lx, size %zu, npages %d, page_shift %d, ncont %d, offset %d\n",
6738e6e287fSHans Petter Selasky addr, size, *npages, *page_shift, *ncont, *offset);
6748e6e287fSHans Petter Selasky
6758e6e287fSHans Petter Selasky return 0;
6768e6e287fSHans Petter Selasky
6778e6e287fSHans Petter Selasky err_umem:
6788e6e287fSHans Petter Selasky ib_umem_release(*umem);
6798e6e287fSHans Petter Selasky *umem = NULL;
6808e6e287fSHans Petter Selasky
6818e6e287fSHans Petter Selasky return err;
6828e6e287fSHans Petter Selasky }
6838e6e287fSHans Petter Selasky
destroy_user_rq(struct ib_pd * pd,struct mlx5_ib_rwq * rwq,struct ib_udata * udata)684b633e08cSHans Petter Selasky static void destroy_user_rq(struct ib_pd *pd, struct mlx5_ib_rwq *rwq,
685b633e08cSHans Petter Selasky struct ib_udata *udata)
6868e6e287fSHans Petter Selasky {
687b633e08cSHans Petter Selasky struct mlx5_ib_ucontext *context =
688b633e08cSHans Petter Selasky rdma_udata_to_drv_context(
689b633e08cSHans Petter Selasky udata,
690b633e08cSHans Petter Selasky struct mlx5_ib_ucontext,
691b633e08cSHans Petter Selasky ibucontext);
6928e6e287fSHans Petter Selasky
6938e6e287fSHans Petter Selasky mlx5_ib_db_unmap_user(context, &rwq->db);
6948e6e287fSHans Petter Selasky if (rwq->umem)
6958e6e287fSHans Petter Selasky ib_umem_release(rwq->umem);
6968e6e287fSHans Petter Selasky }
6978e6e287fSHans Petter Selasky
create_user_rq(struct mlx5_ib_dev * dev,struct ib_pd * pd,struct mlx5_ib_rwq * rwq,struct mlx5_ib_create_wq * ucmd)6988e6e287fSHans Petter Selasky static int create_user_rq(struct mlx5_ib_dev *dev, struct ib_pd *pd,
6998e6e287fSHans Petter Selasky struct mlx5_ib_rwq *rwq,
7008e6e287fSHans Petter Selasky struct mlx5_ib_create_wq *ucmd)
7018e6e287fSHans Petter Selasky {
7028e6e287fSHans Petter Selasky struct mlx5_ib_ucontext *context;
7038e6e287fSHans Petter Selasky int page_shift = 0;
7048e6e287fSHans Petter Selasky int npages;
7058e6e287fSHans Petter Selasky u32 offset = 0;
7068e6e287fSHans Petter Selasky int ncont = 0;
7078e6e287fSHans Petter Selasky int err;
7088e6e287fSHans Petter Selasky
7098e6e287fSHans Petter Selasky if (!ucmd->buf_addr)
7108e6e287fSHans Petter Selasky return -EINVAL;
7118e6e287fSHans Petter Selasky
7128e6e287fSHans Petter Selasky context = to_mucontext(pd->uobject->context);
7138e6e287fSHans Petter Selasky rwq->umem = ib_umem_get(pd->uobject->context, ucmd->buf_addr,
7148e6e287fSHans Petter Selasky rwq->buf_size, 0, 0);
7158e6e287fSHans Petter Selasky if (IS_ERR(rwq->umem)) {
7168e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "umem_get failed\n");
7178e6e287fSHans Petter Selasky err = PTR_ERR(rwq->umem);
7188e6e287fSHans Petter Selasky return err;
7198e6e287fSHans Petter Selasky }
7208e6e287fSHans Petter Selasky
721565cb4e8SHans Petter Selasky mlx5_ib_cont_pages(rwq->umem, ucmd->buf_addr, 0, &npages, &page_shift,
7228e6e287fSHans Petter Selasky &ncont, NULL);
7238e6e287fSHans Petter Selasky err = mlx5_ib_get_buf_offset(ucmd->buf_addr, page_shift,
7248e6e287fSHans Petter Selasky &rwq->rq_page_offset);
7258e6e287fSHans Petter Selasky if (err) {
7268e6e287fSHans Petter Selasky mlx5_ib_warn(dev, "bad offset\n");
7278e6e287fSHans Petter Selasky goto err_umem;
7288e6e287fSHans Petter Selasky }
7298e6e287fSHans Petter Selasky
7308e6e287fSHans Petter Selasky rwq->rq_num_pas = ncont;
7318e6e287fSHans Petter Selasky rwq->page_shift = page_shift;
7328e6e287fSHans Petter Selasky rwq->log_page_size = page_shift - MLX5_ADAPTER_PAGE_SHIFT;
7338e6e287fSHans Petter Selasky rwq->wq_sig = !!(ucmd->flags & MLX5_WQ_FLAG_SIGNATURE);
7348e6e287fSHans Petter Selasky
7358e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "addr 0x%llx, size %zd, npages %d, page_shift %d, ncont %d, offset %d\n",
7368e6e287fSHans Petter Selasky (unsigned long long)ucmd->buf_addr, rwq->buf_size,
7378e6e287fSHans Petter Selasky npages, page_shift, ncont, offset);
7388e6e287fSHans Petter Selasky
7398e6e287fSHans Petter Selasky err = mlx5_ib_db_map_user(context, ucmd->db_addr, &rwq->db);
7408e6e287fSHans Petter Selasky if (err) {
7418e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "map failed\n");
7428e6e287fSHans Petter Selasky goto err_umem;
7438e6e287fSHans Petter Selasky }
7448e6e287fSHans Petter Selasky
7458e6e287fSHans Petter Selasky rwq->create_type = MLX5_WQ_USER;
7468e6e287fSHans Petter Selasky return 0;
7478e6e287fSHans Petter Selasky
7488e6e287fSHans Petter Selasky err_umem:
7498e6e287fSHans Petter Selasky ib_umem_release(rwq->umem);
7508e6e287fSHans Petter Selasky return err;
7518e6e287fSHans Petter Selasky }
7528e6e287fSHans Petter Selasky
adjust_bfregn(struct mlx5_ib_dev * dev,struct mlx5_bfreg_info * bfregi,int bfregn)753f8f5b459SHans Petter Selasky static int adjust_bfregn(struct mlx5_ib_dev *dev,
754f8f5b459SHans Petter Selasky struct mlx5_bfreg_info *bfregi, int bfregn)
755f8f5b459SHans Petter Selasky {
756f8f5b459SHans Petter Selasky return bfregn / MLX5_NON_FP_BFREGS_PER_UAR * MLX5_BFREGS_PER_UAR +
757f8f5b459SHans Petter Selasky bfregn % MLX5_NON_FP_BFREGS_PER_UAR;
758f8f5b459SHans Petter Selasky }
759f8f5b459SHans Petter Selasky
create_user_qp(struct mlx5_ib_dev * dev,struct ib_pd * pd,struct mlx5_ib_qp * qp,struct ib_udata * udata,struct ib_qp_init_attr * attr,u32 ** in,struct mlx5_ib_create_qp_resp * resp,int * inlen,struct mlx5_ib_qp_base * base)76012515907SHans Petter Selasky static int create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
76112515907SHans Petter Selasky struct mlx5_ib_qp *qp, struct ib_udata *udata,
76212515907SHans Petter Selasky struct ib_qp_init_attr *attr,
7638e6e287fSHans Petter Selasky u32 **in,
7648e6e287fSHans Petter Selasky struct mlx5_ib_create_qp_resp *resp, int *inlen,
7658e6e287fSHans Petter Selasky struct mlx5_ib_qp_base *base)
76612515907SHans Petter Selasky {
76712515907SHans Petter Selasky struct mlx5_ib_ucontext *context;
7688e6e287fSHans Petter Selasky struct mlx5_ib_create_qp ucmd;
7698e6e287fSHans Petter Selasky struct mlx5_ib_ubuffer *ubuffer = &base->ubuffer;
77012515907SHans Petter Selasky int page_shift = 0;
771f8f5b459SHans Petter Selasky int uar_index = 0;
77212515907SHans Petter Selasky int npages;
77312515907SHans Petter Selasky u32 offset = 0;
774f8f5b459SHans Petter Selasky int bfregn;
77512515907SHans Petter Selasky int ncont = 0;
7768e6e287fSHans Petter Selasky __be64 *pas;
7778e6e287fSHans Petter Selasky void *qpc;
77812515907SHans Petter Selasky int err;
779b633e08cSHans Petter Selasky u16 uid;
780f8f5b459SHans Petter Selasky u32 uar_flags;
78112515907SHans Petter Selasky
7828e6e287fSHans Petter Selasky err = ib_copy_from_udata(&ucmd, udata, sizeof(ucmd));
7838e6e287fSHans Petter Selasky if (err) {
7848e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "copy failed\n");
7858e6e287fSHans Petter Selasky return err;
7868e6e287fSHans Petter Selasky }
7878e6e287fSHans Petter Selasky
78812515907SHans Petter Selasky context = to_mucontext(pd->uobject->context);
789f8f5b459SHans Petter Selasky uar_flags = ucmd.flags & (MLX5_QP_FLAG_UAR_PAGE_INDEX |
790f8f5b459SHans Petter Selasky MLX5_QP_FLAG_BFREG_INDEX);
791f8f5b459SHans Petter Selasky switch (uar_flags) {
792f8f5b459SHans Petter Selasky case MLX5_QP_FLAG_UAR_PAGE_INDEX:
793f8f5b459SHans Petter Selasky uar_index = ucmd.bfreg_index;
794f8f5b459SHans Petter Selasky bfregn = MLX5_IB_INVALID_BFREG;
795f8f5b459SHans Petter Selasky break;
796f8f5b459SHans Petter Selasky case MLX5_QP_FLAG_BFREG_INDEX:
797f8f5b459SHans Petter Selasky uar_index = bfregn_to_uar_index(dev, &context->bfregi,
798f8f5b459SHans Petter Selasky ucmd.bfreg_index, true);
799f8f5b459SHans Petter Selasky if (uar_index < 0)
800f8f5b459SHans Petter Selasky return uar_index;
801f8f5b459SHans Petter Selasky bfregn = MLX5_IB_INVALID_BFREG;
802f8f5b459SHans Petter Selasky break;
803f8f5b459SHans Petter Selasky case 0:
8048e6e287fSHans Petter Selasky if (qp->flags & MLX5_IB_QP_CROSS_CHANNEL)
805f8f5b459SHans Petter Selasky return -EINVAL;
806f8f5b459SHans Petter Selasky bfregn = alloc_bfreg(dev, &context->bfregi);
807f8f5b459SHans Petter Selasky if (bfregn < 0)
808f8f5b459SHans Petter Selasky return bfregn;
809f8f5b459SHans Petter Selasky break;
810f8f5b459SHans Petter Selasky default:
811f8f5b459SHans Petter Selasky return -EINVAL;
81212515907SHans Petter Selasky }
8138e6e287fSHans Petter Selasky
814f8f5b459SHans Petter Selasky mlx5_ib_dbg(dev, "bfregn 0x%x, uar_index 0x%x\n", bfregn, uar_index);
815f8f5b459SHans Petter Selasky if (bfregn != MLX5_IB_INVALID_BFREG)
816f8f5b459SHans Petter Selasky uar_index = bfregn_to_uar_index(dev, &context->bfregi, bfregn,
817f8f5b459SHans Petter Selasky false);
81812515907SHans Petter Selasky
81912515907SHans Petter Selasky qp->rq.offset = 0;
82012515907SHans Petter Selasky qp->sq.wqe_shift = ilog2(MLX5_SEND_WQE_BB);
82112515907SHans Petter Selasky qp->sq.offset = qp->rq.wqe_cnt << qp->rq.wqe_shift;
82212515907SHans Petter Selasky
8238e6e287fSHans Petter Selasky err = set_user_buf_size(dev, qp, &ucmd, base, attr);
82412515907SHans Petter Selasky if (err)
825f8f5b459SHans Petter Selasky goto err_bfreg;
82612515907SHans Petter Selasky
8278e6e287fSHans Petter Selasky if (ucmd.buf_addr && ubuffer->buf_size) {
8288e6e287fSHans Petter Selasky ubuffer->buf_addr = ucmd.buf_addr;
8298e6e287fSHans Petter Selasky err = mlx5_ib_umem_get(dev, pd, ubuffer->buf_addr,
8308e6e287fSHans Petter Selasky ubuffer->buf_size,
8318e6e287fSHans Petter Selasky &ubuffer->umem, &npages, &page_shift,
8328e6e287fSHans Petter Selasky &ncont, &offset);
8338e6e287fSHans Petter Selasky if (err)
834f8f5b459SHans Petter Selasky goto err_bfreg;
83512515907SHans Petter Selasky } else {
8368e6e287fSHans Petter Selasky ubuffer->umem = NULL;
83712515907SHans Petter Selasky }
83812515907SHans Petter Selasky
8398e6e287fSHans Petter Selasky *inlen = MLX5_ST_SZ_BYTES(create_qp_in) +
8408e6e287fSHans Petter Selasky MLX5_FLD_SZ_BYTES(create_qp_in, pas[0]) * ncont;
84112515907SHans Petter Selasky *in = mlx5_vzalloc(*inlen);
84212515907SHans Petter Selasky if (!*in) {
84312515907SHans Petter Selasky err = -ENOMEM;
84412515907SHans Petter Selasky goto err_umem;
84512515907SHans Petter Selasky }
84612515907SHans Petter Selasky
847b633e08cSHans Petter Selasky uid = (attr->qp_type != IB_QPT_XRC_TGT &&
848b633e08cSHans Petter Selasky attr->qp_type != IB_QPT_XRC_INI) ? to_mpd(pd)->uid : 0;
849b633e08cSHans Petter Selasky MLX5_SET(create_qp_in, *in, uid, uid);
8508e6e287fSHans Petter Selasky pas = (__be64 *)MLX5_ADDR_OF(create_qp_in, *in, pas);
8518e6e287fSHans Petter Selasky if (ubuffer->umem)
8528e6e287fSHans Petter Selasky mlx5_ib_populate_pas(dev, ubuffer->umem, page_shift, pas, 0);
8538e6e287fSHans Petter Selasky
8548e6e287fSHans Petter Selasky qpc = MLX5_ADDR_OF(create_qp_in, *in, qpc);
8558e6e287fSHans Petter Selasky
8568e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, log_page_size, page_shift - MLX5_ADAPTER_PAGE_SHIFT);
8578e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, page_offset, offset);
8588e6e287fSHans Petter Selasky
8598e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, uar_page, uar_index);
860f8f5b459SHans Petter Selasky if (bfregn != MLX5_IB_INVALID_BFREG)
861f8f5b459SHans Petter Selasky resp->bfreg_index = adjust_bfregn(dev, &context->bfregi, bfregn);
862f8f5b459SHans Petter Selasky else
863f8f5b459SHans Petter Selasky resp->bfreg_index = MLX5_IB_INVALID_BFREG;
864f8f5b459SHans Petter Selasky qp->bfregn = bfregn;
86512515907SHans Petter Selasky
8668e6e287fSHans Petter Selasky err = mlx5_ib_db_map_user(context, ucmd.db_addr, &qp->db);
86712515907SHans Petter Selasky if (err) {
8688e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "map failed\n");
86912515907SHans Petter Selasky goto err_free;
87012515907SHans Petter Selasky }
87112515907SHans Petter Selasky
8728e6e287fSHans Petter Selasky err = ib_copy_to_udata(udata, resp, sizeof(*resp));
87312515907SHans Petter Selasky if (err) {
8748e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "copy failed\n");
87512515907SHans Petter Selasky goto err_unmap;
87612515907SHans Petter Selasky }
87712515907SHans Petter Selasky qp->create_type = MLX5_QP_USER;
87812515907SHans Petter Selasky
87912515907SHans Petter Selasky return 0;
88012515907SHans Petter Selasky
88112515907SHans Petter Selasky err_unmap:
88212515907SHans Petter Selasky mlx5_ib_db_unmap_user(context, &qp->db);
88312515907SHans Petter Selasky
88412515907SHans Petter Selasky err_free:
88512515907SHans Petter Selasky kvfree(*in);
88612515907SHans Petter Selasky
88712515907SHans Petter Selasky err_umem:
8888e6e287fSHans Petter Selasky if (ubuffer->umem)
8898e6e287fSHans Petter Selasky ib_umem_release(ubuffer->umem);
89012515907SHans Petter Selasky
891f8f5b459SHans Petter Selasky err_bfreg:
892f8f5b459SHans Petter Selasky if (bfregn != MLX5_IB_INVALID_BFREG)
893f8f5b459SHans Petter Selasky mlx5_ib_free_bfreg(dev, &context->bfregi, bfregn);
89412515907SHans Petter Selasky return err;
89512515907SHans Petter Selasky }
89612515907SHans Petter Selasky
destroy_qp_user(struct mlx5_ib_dev * dev,struct ib_pd * pd,struct mlx5_ib_qp * qp,struct mlx5_ib_qp_base * base,struct ib_udata * udata)897f8f5b459SHans Petter Selasky static void destroy_qp_user(struct mlx5_ib_dev *dev, struct ib_pd *pd, struct mlx5_ib_qp *qp,
898b633e08cSHans Petter Selasky struct mlx5_ib_qp_base *base,
899b633e08cSHans Petter Selasky struct ib_udata *udata)
90012515907SHans Petter Selasky {
901b633e08cSHans Petter Selasky struct mlx5_ib_ucontext *context =
902b633e08cSHans Petter Selasky rdma_udata_to_drv_context(
903b633e08cSHans Petter Selasky udata,
904b633e08cSHans Petter Selasky struct mlx5_ib_ucontext,
905b633e08cSHans Petter Selasky ibucontext);
90612515907SHans Petter Selasky
90712515907SHans Petter Selasky mlx5_ib_db_unmap_user(context, &qp->db);
9088e6e287fSHans Petter Selasky if (base->ubuffer.umem)
9098e6e287fSHans Petter Selasky ib_umem_release(base->ubuffer.umem);
910f8f5b459SHans Petter Selasky
911f8f5b459SHans Petter Selasky /*
912f8f5b459SHans Petter Selasky * Free only the BFREGs which are handled by the kernel.
913f8f5b459SHans Petter Selasky * BFREGs of UARs allocated dynamically are handled by user.
914f8f5b459SHans Petter Selasky */
915f8f5b459SHans Petter Selasky if (qp->bfregn != MLX5_IB_INVALID_BFREG)
916f8f5b459SHans Petter Selasky mlx5_ib_free_bfreg(dev, &context->bfregi, qp->bfregn);
91712515907SHans Petter Selasky }
91812515907SHans Petter Selasky
create_kernel_qp(struct mlx5_ib_dev * dev,struct ib_qp_init_attr * init_attr,struct mlx5_ib_qp * qp,u32 ** in,int * inlen,struct mlx5_ib_qp_base * base)91912515907SHans Petter Selasky static int create_kernel_qp(struct mlx5_ib_dev *dev,
92012515907SHans Petter Selasky struct ib_qp_init_attr *init_attr,
92112515907SHans Petter Selasky struct mlx5_ib_qp *qp,
9228e6e287fSHans Petter Selasky u32 **in, int *inlen,
9238e6e287fSHans Petter Selasky struct mlx5_ib_qp_base *base)
92412515907SHans Petter Selasky {
92512515907SHans Petter Selasky int uar_index;
9268e6e287fSHans Petter Selasky void *qpc;
92712515907SHans Petter Selasky int err;
92812515907SHans Petter Selasky
9298e6e287fSHans Petter Selasky if (init_attr->create_flags & ~(IB_QP_CREATE_SIGNATURE_EN |
9308e6e287fSHans Petter Selasky IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK |
9318e6e287fSHans Petter Selasky IB_QP_CREATE_IPOIB_UD_LSO |
932f8f5b459SHans Petter Selasky MLX5_IB_QP_CREATE_SQPN_QP1 |
933f8f5b459SHans Petter Selasky MLX5_IB_QP_CREATE_WC_TEST))
93412515907SHans Petter Selasky return -EINVAL;
93512515907SHans Petter Selasky
936f8f5b459SHans Petter Selasky spin_lock_init(&qp->bf.lock32);
937f8f5b459SHans Petter Selasky
9388e6e287fSHans Petter Selasky if (init_attr->qp_type == MLX5_IB_QPT_REG_UMR)
939f8f5b459SHans Petter Selasky qp->bf.bfreg = &dev->fp_bfreg;
940f8f5b459SHans Petter Selasky else if (init_attr->create_flags & MLX5_IB_QP_CREATE_WC_TEST)
941f8f5b459SHans Petter Selasky qp->bf.bfreg = &dev->wc_bfreg;
942f8f5b459SHans Petter Selasky else
943f8f5b459SHans Petter Selasky qp->bf.bfreg = &dev->bfreg;
9448e6e287fSHans Petter Selasky
945f8f5b459SHans Petter Selasky /* We need to divide by two since each register is comprised of
946f8f5b459SHans Petter Selasky * two buffers of identical size, namely odd and even
947f8f5b459SHans Petter Selasky */
948f8f5b459SHans Petter Selasky qp->bf.buf_size = (1 << MLX5_CAP_GEN(dev->mdev, log_bf_reg_size)) / 2;
949f8f5b459SHans Petter Selasky uar_index = qp->bf.bfreg->index;
95012515907SHans Petter Selasky
95112515907SHans Petter Selasky err = calc_sq_size(dev, init_attr, qp);
95212515907SHans Petter Selasky if (err < 0) {
9538e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "err %d\n", err);
954f8f5b459SHans Petter Selasky return err;
95512515907SHans Petter Selasky }
95612515907SHans Petter Selasky
95712515907SHans Petter Selasky qp->rq.offset = 0;
95812515907SHans Petter Selasky qp->sq.offset = qp->rq.wqe_cnt << qp->rq.wqe_shift;
9598e6e287fSHans Petter Selasky base->ubuffer.buf_size = err + (qp->rq.wqe_cnt << qp->rq.wqe_shift);
96012515907SHans Petter Selasky
9618e6e287fSHans Petter Selasky err = mlx5_buf_alloc(dev->mdev, base->ubuffer.buf_size,
9628e6e287fSHans Petter Selasky 2 * PAGE_SIZE, &qp->buf);
96312515907SHans Petter Selasky if (err) {
9648e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "err %d\n", err);
965f8f5b459SHans Petter Selasky return err;
96612515907SHans Petter Selasky }
96712515907SHans Petter Selasky
96812515907SHans Petter Selasky qp->sq.qend = mlx5_get_send_wqe(qp, qp->sq.wqe_cnt);
9698e6e287fSHans Petter Selasky *inlen = MLX5_ST_SZ_BYTES(create_qp_in) +
9708e6e287fSHans Petter Selasky MLX5_FLD_SZ_BYTES(create_qp_in, pas[0]) * qp->buf.npages;
97112515907SHans Petter Selasky *in = mlx5_vzalloc(*inlen);
97212515907SHans Petter Selasky if (!*in) {
97312515907SHans Petter Selasky err = -ENOMEM;
97412515907SHans Petter Selasky goto err_buf;
97512515907SHans Petter Selasky }
97612515907SHans Petter Selasky
9778e6e287fSHans Petter Selasky qpc = MLX5_ADDR_OF(create_qp_in, *in, qpc);
9788e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, uar_page, uar_index);
9794fb0a74eSHans Petter Selasky MLX5_SET(qpc, qpc, ts_format, mlx5_get_qp_default_ts(dev->mdev));
9808e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, log_page_size, qp->buf.page_shift - MLX5_ADAPTER_PAGE_SHIFT);
9818e6e287fSHans Petter Selasky
9828e6e287fSHans Petter Selasky /* Set "fast registration enabled" for all kernel QPs */
9838e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, fre, 1);
9848e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, rlky, 1);
9858e6e287fSHans Petter Selasky
986f8f5b459SHans Petter Selasky if (init_attr->create_flags & MLX5_IB_QP_CREATE_SQPN_QP1) {
9878e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, deth_sqpn, 1);
9888e6e287fSHans Petter Selasky qp->flags |= MLX5_IB_QP_SQPN_QP1;
9898e6e287fSHans Petter Selasky }
9908e6e287fSHans Petter Selasky
9918e6e287fSHans Petter Selasky mlx5_fill_page_array(&qp->buf,
9928e6e287fSHans Petter Selasky (__be64 *)MLX5_ADDR_OF(create_qp_in, *in, pas));
99312515907SHans Petter Selasky
99412515907SHans Petter Selasky err = mlx5_db_alloc(dev->mdev, &qp->db);
99512515907SHans Petter Selasky if (err) {
9968e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "err %d\n", err);
99712515907SHans Petter Selasky goto err_free;
99812515907SHans Petter Selasky }
99912515907SHans Petter Selasky
10008e6e287fSHans Petter Selasky qp->sq.wrid = kmalloc(qp->sq.wqe_cnt * sizeof(*qp->sq.wrid), GFP_KERNEL);
10018e6e287fSHans Petter Selasky qp->sq.wr_data = kmalloc(qp->sq.wqe_cnt * sizeof(*qp->sq.wr_data), GFP_KERNEL);
10028e6e287fSHans Petter Selasky qp->rq.wrid = kmalloc(qp->rq.wqe_cnt * sizeof(*qp->rq.wrid), GFP_KERNEL);
10038e6e287fSHans Petter Selasky qp->sq.w_list = kmalloc(qp->sq.wqe_cnt * sizeof(*qp->sq.w_list), GFP_KERNEL);
10048e6e287fSHans Petter Selasky qp->sq.wqe_head = kmalloc(qp->sq.wqe_cnt * sizeof(*qp->sq.wqe_head), GFP_KERNEL);
10058e6e287fSHans Petter Selasky
10068e6e287fSHans Petter Selasky if (!qp->sq.wrid || !qp->sq.wr_data || !qp->rq.wrid ||
10078e6e287fSHans Petter Selasky !qp->sq.w_list || !qp->sq.wqe_head) {
100812515907SHans Petter Selasky err = -ENOMEM;
100912515907SHans Petter Selasky goto err_wrid;
101012515907SHans Petter Selasky }
101112515907SHans Petter Selasky qp->create_type = MLX5_QP_KERNEL;
101212515907SHans Petter Selasky
101312515907SHans Petter Selasky return 0;
101412515907SHans Petter Selasky
101512515907SHans Petter Selasky err_wrid:
10168e6e287fSHans Petter Selasky kfree(qp->sq.wqe_head);
10178e6e287fSHans Petter Selasky kfree(qp->sq.w_list);
10188e6e287fSHans Petter Selasky kfree(qp->sq.wrid);
10198e6e287fSHans Petter Selasky kfree(qp->sq.wr_data);
10208e6e287fSHans Petter Selasky kfree(qp->rq.wrid);
10218114aeeaSHans Petter Selasky mlx5_db_free(dev->mdev, &qp->db);
102212515907SHans Petter Selasky
102312515907SHans Petter Selasky err_free:
102412515907SHans Petter Selasky kvfree(*in);
102512515907SHans Petter Selasky
102612515907SHans Petter Selasky err_buf:
102712515907SHans Petter Selasky mlx5_buf_free(dev->mdev, &qp->buf);
102812515907SHans Petter Selasky return err;
102912515907SHans Petter Selasky }
103012515907SHans Petter Selasky
destroy_qp_kernel(struct mlx5_ib_dev * dev,struct mlx5_ib_qp * qp)103112515907SHans Petter Selasky static void destroy_qp_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp)
103212515907SHans Petter Selasky {
10338e6e287fSHans Petter Selasky kfree(qp->sq.wqe_head);
10348e6e287fSHans Petter Selasky kfree(qp->sq.w_list);
10358e6e287fSHans Petter Selasky kfree(qp->sq.wrid);
10368e6e287fSHans Petter Selasky kfree(qp->sq.wr_data);
10378e6e287fSHans Petter Selasky kfree(qp->rq.wrid);
10388114aeeaSHans Petter Selasky mlx5_db_free(dev->mdev, &qp->db);
103912515907SHans Petter Selasky mlx5_buf_free(dev->mdev, &qp->buf);
104012515907SHans Petter Selasky }
104112515907SHans Petter Selasky
get_rx_type(struct mlx5_ib_qp * qp,struct ib_qp_init_attr * attr)10428e6e287fSHans Petter Selasky static u32 get_rx_type(struct mlx5_ib_qp *qp, struct ib_qp_init_attr *attr)
104312515907SHans Petter Selasky {
10448e6e287fSHans Petter Selasky if (attr->srq || (attr->qp_type == IB_QPT_XRC_TGT) ||
10458e6e287fSHans Petter Selasky (attr->qp_type == IB_QPT_XRC_INI))
10468e6e287fSHans Petter Selasky return MLX5_SRQ_RQ;
104712515907SHans Petter Selasky else if (!qp->has_rq)
10488e6e287fSHans Petter Selasky return MLX5_ZERO_LEN_RQ;
104912515907SHans Petter Selasky else
10508e6e287fSHans Petter Selasky return MLX5_NON_ZERO_RQ;
105112515907SHans Petter Selasky }
105212515907SHans Petter Selasky
is_connected(enum ib_qp_type qp_type)105312515907SHans Petter Selasky static int is_connected(enum ib_qp_type qp_type)
105412515907SHans Petter Selasky {
105512515907SHans Petter Selasky if (qp_type == IB_QPT_RC || qp_type == IB_QPT_UC)
105612515907SHans Petter Selasky return 1;
105712515907SHans Petter Selasky
105812515907SHans Petter Selasky return 0;
105912515907SHans Petter Selasky }
106012515907SHans Petter Selasky
create_raw_packet_qp_tis(struct mlx5_ib_dev * dev,struct mlx5_ib_sq * sq,u32 tdn,struct ib_pd * pd)10618e6e287fSHans Petter Selasky static int create_raw_packet_qp_tis(struct mlx5_ib_dev *dev,
1062b633e08cSHans Petter Selasky struct mlx5_ib_sq *sq, u32 tdn,
1063b633e08cSHans Petter Selasky struct ib_pd *pd)
106412515907SHans Petter Selasky {
10658e6e287fSHans Petter Selasky u32 in[MLX5_ST_SZ_DW(create_tis_in)] = {0};
10668e6e287fSHans Petter Selasky void *tisc = MLX5_ADDR_OF(create_tis_in, in, ctx);
106712515907SHans Petter Selasky
1068b633e08cSHans Petter Selasky MLX5_SET(create_tis_in, in, uid, to_mpd(pd)->uid);
10698e6e287fSHans Petter Selasky MLX5_SET(tisc, tisc, transport_domain, tdn);
10708e6e287fSHans Petter Selasky return mlx5_core_create_tis(dev->mdev, in, sizeof(in), &sq->tisn);
10718e6e287fSHans Petter Selasky }
107212515907SHans Petter Selasky
destroy_raw_packet_qp_tis(struct mlx5_ib_dev * dev,struct mlx5_ib_sq * sq,struct ib_pd * pd)10738e6e287fSHans Petter Selasky static void destroy_raw_packet_qp_tis(struct mlx5_ib_dev *dev,
1074b633e08cSHans Petter Selasky struct mlx5_ib_sq *sq, struct ib_pd *pd)
10758e6e287fSHans Petter Selasky {
1076b633e08cSHans Petter Selasky mlx5_core_destroy_tis(dev->mdev, sq->tisn, to_mpd(pd)->uid);
10778e6e287fSHans Petter Selasky }
10788e6e287fSHans Petter Selasky
create_raw_packet_qp_sq(struct mlx5_ib_dev * dev,struct mlx5_ib_sq * sq,void * qpin,struct ib_pd * pd)10798e6e287fSHans Petter Selasky static int create_raw_packet_qp_sq(struct mlx5_ib_dev *dev,
10808e6e287fSHans Petter Selasky struct mlx5_ib_sq *sq, void *qpin,
10818e6e287fSHans Petter Selasky struct ib_pd *pd)
10828e6e287fSHans Petter Selasky {
10838e6e287fSHans Petter Selasky struct mlx5_ib_ubuffer *ubuffer = &sq->ubuffer;
10848e6e287fSHans Petter Selasky __be64 *pas;
10858e6e287fSHans Petter Selasky void *in;
10868e6e287fSHans Petter Selasky void *sqc;
10878e6e287fSHans Petter Selasky void *qpc = MLX5_ADDR_OF(create_qp_in, qpin, qpc);
10888e6e287fSHans Petter Selasky void *wq;
10898e6e287fSHans Petter Selasky int inlen;
10908e6e287fSHans Petter Selasky int err;
10918e6e287fSHans Petter Selasky int page_shift = 0;
10928e6e287fSHans Petter Selasky int npages;
10938e6e287fSHans Petter Selasky int ncont = 0;
10948e6e287fSHans Petter Selasky u32 offset = 0;
10954fb0a74eSHans Petter Selasky u8 ts_format;
10964fb0a74eSHans Petter Selasky
10974fb0a74eSHans Petter Selasky ts_format = mlx5_get_sq_default_ts(dev->mdev);
10988e6e287fSHans Petter Selasky
10998e6e287fSHans Petter Selasky err = mlx5_ib_umem_get(dev, pd, ubuffer->buf_addr, ubuffer->buf_size,
11008e6e287fSHans Petter Selasky &sq->ubuffer.umem, &npages, &page_shift,
11018e6e287fSHans Petter Selasky &ncont, &offset);
11028e6e287fSHans Petter Selasky if (err)
11038e6e287fSHans Petter Selasky return err;
11048e6e287fSHans Petter Selasky
11058e6e287fSHans Petter Selasky inlen = MLX5_ST_SZ_BYTES(create_sq_in) + sizeof(u64) * ncont;
11068e6e287fSHans Petter Selasky in = mlx5_vzalloc(inlen);
11078e6e287fSHans Petter Selasky if (!in) {
11088e6e287fSHans Petter Selasky err = -ENOMEM;
11098e6e287fSHans Petter Selasky goto err_umem;
11108e6e287fSHans Petter Selasky }
11118e6e287fSHans Petter Selasky
1112b633e08cSHans Petter Selasky MLX5_SET(create_sq_in, in, uid, to_mpd(pd)->uid);
11138e6e287fSHans Petter Selasky sqc = MLX5_ADDR_OF(create_sq_in, in, ctx);
11148e6e287fSHans Petter Selasky MLX5_SET(sqc, sqc, flush_in_error_en, 1);
11158e6e287fSHans Petter Selasky MLX5_SET(sqc, sqc, state, MLX5_SQC_STATE_RST);
11164fb0a74eSHans Petter Selasky MLX5_SET(sqc, sqc, ts_format, ts_format);
11178e6e287fSHans Petter Selasky MLX5_SET(sqc, sqc, user_index, MLX5_GET(qpc, qpc, user_index));
11188e6e287fSHans Petter Selasky MLX5_SET(sqc, sqc, cqn, MLX5_GET(qpc, qpc, cqn_snd));
11198e6e287fSHans Petter Selasky MLX5_SET(sqc, sqc, tis_lst_sz, 1);
11208e6e287fSHans Petter Selasky MLX5_SET(sqc, sqc, tis_num_0, sq->tisn);
11218e6e287fSHans Petter Selasky
11228e6e287fSHans Petter Selasky wq = MLX5_ADDR_OF(sqc, sqc, wq);
11238e6e287fSHans Petter Selasky MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_CYCLIC);
11248e6e287fSHans Petter Selasky MLX5_SET(wq, wq, pd, MLX5_GET(qpc, qpc, pd));
11258e6e287fSHans Petter Selasky MLX5_SET(wq, wq, uar_page, MLX5_GET(qpc, qpc, uar_page));
11268e6e287fSHans Petter Selasky MLX5_SET64(wq, wq, dbr_addr, MLX5_GET64(qpc, qpc, dbr_addr));
11278e6e287fSHans Petter Selasky MLX5_SET(wq, wq, log_wq_stride, ilog2(MLX5_SEND_WQE_BB));
11288e6e287fSHans Petter Selasky MLX5_SET(wq, wq, log_wq_sz, MLX5_GET(qpc, qpc, log_sq_size));
11298e6e287fSHans Petter Selasky MLX5_SET(wq, wq, log_wq_pg_sz, page_shift - MLX5_ADAPTER_PAGE_SHIFT);
11308e6e287fSHans Petter Selasky MLX5_SET(wq, wq, page_offset, offset);
11318e6e287fSHans Petter Selasky
11328e6e287fSHans Petter Selasky pas = (__be64 *)MLX5_ADDR_OF(wq, wq, pas);
11338e6e287fSHans Petter Selasky mlx5_ib_populate_pas(dev, sq->ubuffer.umem, page_shift, pas, 0);
11348e6e287fSHans Petter Selasky
11358e6e287fSHans Petter Selasky err = mlx5_core_create_sq_tracked(dev->mdev, in, inlen, &sq->base.mqp);
11368e6e287fSHans Petter Selasky
11378e6e287fSHans Petter Selasky kvfree(in);
11388e6e287fSHans Petter Selasky
11398e6e287fSHans Petter Selasky if (err)
11408e6e287fSHans Petter Selasky goto err_umem;
11418e6e287fSHans Petter Selasky
11428e6e287fSHans Petter Selasky return 0;
11438e6e287fSHans Petter Selasky
11448e6e287fSHans Petter Selasky err_umem:
11458e6e287fSHans Petter Selasky ib_umem_release(sq->ubuffer.umem);
11468e6e287fSHans Petter Selasky sq->ubuffer.umem = NULL;
11478e6e287fSHans Petter Selasky
11488e6e287fSHans Petter Selasky return err;
11498e6e287fSHans Petter Selasky }
11508e6e287fSHans Petter Selasky
destroy_raw_packet_qp_sq(struct mlx5_ib_dev * dev,struct mlx5_ib_sq * sq)11518e6e287fSHans Petter Selasky static void destroy_raw_packet_qp_sq(struct mlx5_ib_dev *dev,
11528e6e287fSHans Petter Selasky struct mlx5_ib_sq *sq)
11538e6e287fSHans Petter Selasky {
11548e6e287fSHans Petter Selasky mlx5_core_destroy_sq_tracked(dev->mdev, &sq->base.mqp);
11558e6e287fSHans Petter Selasky ib_umem_release(sq->ubuffer.umem);
11568e6e287fSHans Petter Selasky }
11578e6e287fSHans Petter Selasky
get_rq_pas_size(void * qpc)11588e6e287fSHans Petter Selasky static int get_rq_pas_size(void *qpc)
11598e6e287fSHans Petter Selasky {
11608e6e287fSHans Petter Selasky u32 log_page_size = MLX5_GET(qpc, qpc, log_page_size) + 12;
11618e6e287fSHans Petter Selasky u32 log_rq_stride = MLX5_GET(qpc, qpc, log_rq_stride);
11628e6e287fSHans Petter Selasky u32 log_rq_size = MLX5_GET(qpc, qpc, log_rq_size);
11638e6e287fSHans Petter Selasky u32 page_offset = MLX5_GET(qpc, qpc, page_offset);
11648e6e287fSHans Petter Selasky u32 po_quanta = 1 << (log_page_size - 6);
11658e6e287fSHans Petter Selasky u32 rq_sz = 1 << (log_rq_size + 4 + log_rq_stride);
11668e6e287fSHans Petter Selasky u32 page_size = 1 << log_page_size;
11678e6e287fSHans Petter Selasky u32 rq_sz_po = rq_sz + (page_offset * po_quanta);
11688e6e287fSHans Petter Selasky u32 rq_num_pas = (rq_sz_po + page_size - 1) / page_size;
11698e6e287fSHans Petter Selasky
11708e6e287fSHans Petter Selasky return rq_num_pas * sizeof(u64);
11718e6e287fSHans Petter Selasky }
11728e6e287fSHans Petter Selasky
create_raw_packet_qp_rq(struct mlx5_ib_dev * dev,struct mlx5_ib_rq * rq,void * qpin,struct ib_pd * pd)11738e6e287fSHans Petter Selasky static int create_raw_packet_qp_rq(struct mlx5_ib_dev *dev,
1174b633e08cSHans Petter Selasky struct mlx5_ib_rq *rq, void *qpin,
1175b633e08cSHans Petter Selasky struct ib_pd *pd)
11768e6e287fSHans Petter Selasky {
11778e6e287fSHans Petter Selasky struct mlx5_ib_qp *mqp = rq->base.container_mibqp;
11788e6e287fSHans Petter Selasky __be64 *pas;
11798e6e287fSHans Petter Selasky __be64 *qp_pas;
11808e6e287fSHans Petter Selasky void *in;
11818e6e287fSHans Petter Selasky void *rqc;
11828e6e287fSHans Petter Selasky void *wq;
11838e6e287fSHans Petter Selasky void *qpc = MLX5_ADDR_OF(create_qp_in, qpin, qpc);
11848e6e287fSHans Petter Selasky int inlen;
11858e6e287fSHans Petter Selasky int err;
11868e6e287fSHans Petter Selasky u32 rq_pas_size = get_rq_pas_size(qpc);
11874fb0a74eSHans Petter Selasky u8 ts_format;
11884fb0a74eSHans Petter Selasky
11894fb0a74eSHans Petter Selasky ts_format = mlx5_get_rq_default_ts(dev->mdev);
11908e6e287fSHans Petter Selasky
11918e6e287fSHans Petter Selasky inlen = MLX5_ST_SZ_BYTES(create_rq_in) + rq_pas_size;
11928e6e287fSHans Petter Selasky in = mlx5_vzalloc(inlen);
11938e6e287fSHans Petter Selasky if (!in)
11948e6e287fSHans Petter Selasky return -ENOMEM;
11958e6e287fSHans Petter Selasky
1196b633e08cSHans Petter Selasky MLX5_SET(create_rq_in, in, uid, to_mpd(pd)->uid);
11978e6e287fSHans Petter Selasky rqc = MLX5_ADDR_OF(create_rq_in, in, ctx);
11988e6e287fSHans Petter Selasky MLX5_SET(rqc, rqc, vlan_strip_disable, 1);
11998e6e287fSHans Petter Selasky MLX5_SET(rqc, rqc, mem_rq_type, MLX5_RQC_RQ_TYPE_MEMORY_RQ_INLINE);
12008e6e287fSHans Petter Selasky MLX5_SET(rqc, rqc, state, MLX5_RQC_STATE_RST);
12014fb0a74eSHans Petter Selasky MLX5_SET(rqc, rqc, ts_format, ts_format);
12028e6e287fSHans Petter Selasky MLX5_SET(rqc, rqc, flush_in_error_en, 1);
12038e6e287fSHans Petter Selasky MLX5_SET(rqc, rqc, user_index, MLX5_GET(qpc, qpc, user_index));
12048e6e287fSHans Petter Selasky MLX5_SET(rqc, rqc, cqn, MLX5_GET(qpc, qpc, cqn_rcv));
12058e6e287fSHans Petter Selasky
12068e6e287fSHans Petter Selasky if (mqp->flags & MLX5_IB_QP_CAP_SCATTER_FCS)
12078e6e287fSHans Petter Selasky MLX5_SET(rqc, rqc, scatter_fcs, 1);
12088e6e287fSHans Petter Selasky
12098e6e287fSHans Petter Selasky wq = MLX5_ADDR_OF(rqc, rqc, wq);
12108e6e287fSHans Petter Selasky MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_CYCLIC);
12118e6e287fSHans Petter Selasky MLX5_SET(wq, wq, end_padding_mode,
12128e6e287fSHans Petter Selasky MLX5_GET(qpc, qpc, end_padding_mode));
12138e6e287fSHans Petter Selasky MLX5_SET(wq, wq, page_offset, MLX5_GET(qpc, qpc, page_offset));
12148e6e287fSHans Petter Selasky MLX5_SET(wq, wq, pd, MLX5_GET(qpc, qpc, pd));
12158e6e287fSHans Petter Selasky MLX5_SET64(wq, wq, dbr_addr, MLX5_GET64(qpc, qpc, dbr_addr));
12168e6e287fSHans Petter Selasky MLX5_SET(wq, wq, log_wq_stride, MLX5_GET(qpc, qpc, log_rq_stride) + 4);
12178e6e287fSHans Petter Selasky MLX5_SET(wq, wq, log_wq_pg_sz, MLX5_GET(qpc, qpc, log_page_size));
12188e6e287fSHans Petter Selasky MLX5_SET(wq, wq, log_wq_sz, MLX5_GET(qpc, qpc, log_rq_size));
12198e6e287fSHans Petter Selasky
12208e6e287fSHans Petter Selasky pas = (__be64 *)MLX5_ADDR_OF(wq, wq, pas);
12218e6e287fSHans Petter Selasky qp_pas = (__be64 *)MLX5_ADDR_OF(create_qp_in, qpin, pas);
12228e6e287fSHans Petter Selasky memcpy(pas, qp_pas, rq_pas_size);
12238e6e287fSHans Petter Selasky
12248e6e287fSHans Petter Selasky err = mlx5_core_create_rq_tracked(dev->mdev, in, inlen, &rq->base.mqp);
12258e6e287fSHans Petter Selasky
12268e6e287fSHans Petter Selasky kvfree(in);
12278e6e287fSHans Petter Selasky
12288e6e287fSHans Petter Selasky return err;
12298e6e287fSHans Petter Selasky }
12308e6e287fSHans Petter Selasky
destroy_raw_packet_qp_rq(struct mlx5_ib_dev * dev,struct mlx5_ib_rq * rq)12318e6e287fSHans Petter Selasky static void destroy_raw_packet_qp_rq(struct mlx5_ib_dev *dev,
12328e6e287fSHans Petter Selasky struct mlx5_ib_rq *rq)
12338e6e287fSHans Petter Selasky {
12348e6e287fSHans Petter Selasky mlx5_core_destroy_rq_tracked(dev->mdev, &rq->base.mqp);
12358e6e287fSHans Petter Selasky }
12368e6e287fSHans Petter Selasky
create_raw_packet_qp_tir(struct mlx5_ib_dev * dev,struct mlx5_ib_rq * rq,u32 tdn,struct ib_pd * pd)12378e6e287fSHans Petter Selasky static int create_raw_packet_qp_tir(struct mlx5_ib_dev *dev,
1238b633e08cSHans Petter Selasky struct mlx5_ib_rq *rq, u32 tdn,
1239b633e08cSHans Petter Selasky struct ib_pd *pd)
12408e6e287fSHans Petter Selasky {
12418e6e287fSHans Petter Selasky u32 *in;
12428e6e287fSHans Petter Selasky void *tirc;
12438e6e287fSHans Petter Selasky int inlen;
12448e6e287fSHans Petter Selasky int err;
12458e6e287fSHans Petter Selasky
12468e6e287fSHans Petter Selasky inlen = MLX5_ST_SZ_BYTES(create_tir_in);
12478e6e287fSHans Petter Selasky in = mlx5_vzalloc(inlen);
12488e6e287fSHans Petter Selasky if (!in)
12498e6e287fSHans Petter Selasky return -ENOMEM;
12508e6e287fSHans Petter Selasky
1251b633e08cSHans Petter Selasky MLX5_SET(create_tir_in, in, uid, to_mpd(pd)->uid);
12528e6e287fSHans Petter Selasky tirc = MLX5_ADDR_OF(create_tir_in, in, tir_context);
12538e6e287fSHans Petter Selasky MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_DIRECT);
12548e6e287fSHans Petter Selasky MLX5_SET(tirc, tirc, inline_rqn, rq->base.mqp.qpn);
12558e6e287fSHans Petter Selasky MLX5_SET(tirc, tirc, transport_domain, tdn);
12568e6e287fSHans Petter Selasky
12578e6e287fSHans Petter Selasky err = mlx5_core_create_tir(dev->mdev, in, inlen, &rq->tirn);
12588e6e287fSHans Petter Selasky
12598e6e287fSHans Petter Selasky kvfree(in);
12608e6e287fSHans Petter Selasky
12618e6e287fSHans Petter Selasky return err;
12628e6e287fSHans Petter Selasky }
12638e6e287fSHans Petter Selasky
destroy_raw_packet_qp_tir(struct mlx5_ib_dev * dev,struct mlx5_ib_rq * rq,struct ib_pd * pd)12648e6e287fSHans Petter Selasky static void destroy_raw_packet_qp_tir(struct mlx5_ib_dev *dev,
1265b633e08cSHans Petter Selasky struct mlx5_ib_rq *rq,
1266b633e08cSHans Petter Selasky struct ib_pd *pd)
12678e6e287fSHans Petter Selasky {
1268b633e08cSHans Petter Selasky mlx5_core_destroy_tir(dev->mdev, rq->tirn, to_mpd(pd)->uid);
12698e6e287fSHans Petter Selasky }
12708e6e287fSHans Petter Selasky
create_raw_packet_qp(struct mlx5_ib_dev * dev,struct mlx5_ib_qp * qp,u32 * in,struct ib_pd * pd)12718e6e287fSHans Petter Selasky static int create_raw_packet_qp(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
12728e6e287fSHans Petter Selasky u32 *in,
12738e6e287fSHans Petter Selasky struct ib_pd *pd)
12748e6e287fSHans Petter Selasky {
12758e6e287fSHans Petter Selasky struct mlx5_ib_raw_packet_qp *raw_packet_qp = &qp->raw_packet_qp;
12768e6e287fSHans Petter Selasky struct mlx5_ib_sq *sq = &raw_packet_qp->sq;
12778e6e287fSHans Petter Selasky struct mlx5_ib_rq *rq = &raw_packet_qp->rq;
12788e6e287fSHans Petter Selasky struct ib_uobject *uobj = pd->uobject;
12798e6e287fSHans Petter Selasky struct ib_ucontext *ucontext = uobj->context;
12808e6e287fSHans Petter Selasky struct mlx5_ib_ucontext *mucontext = to_mucontext(ucontext);
12818e6e287fSHans Petter Selasky int err;
12828e6e287fSHans Petter Selasky u32 tdn = mucontext->tdn;
12838e6e287fSHans Petter Selasky
12848e6e287fSHans Petter Selasky if (qp->sq.wqe_cnt) {
1285b633e08cSHans Petter Selasky err = create_raw_packet_qp_tis(dev, sq, tdn, pd);
12868e6e287fSHans Petter Selasky if (err)
12878e6e287fSHans Petter Selasky return err;
12888e6e287fSHans Petter Selasky
12898e6e287fSHans Petter Selasky err = create_raw_packet_qp_sq(dev, sq, in, pd);
12908e6e287fSHans Petter Selasky if (err)
12918e6e287fSHans Petter Selasky goto err_destroy_tis;
12928e6e287fSHans Petter Selasky
12938e6e287fSHans Petter Selasky sq->base.container_mibqp = qp;
12948e6e287fSHans Petter Selasky }
12958e6e287fSHans Petter Selasky
12968e6e287fSHans Petter Selasky if (qp->rq.wqe_cnt) {
12978e6e287fSHans Petter Selasky rq->base.container_mibqp = qp;
12988e6e287fSHans Petter Selasky
1299b633e08cSHans Petter Selasky err = create_raw_packet_qp_rq(dev, rq, in, pd);
13008e6e287fSHans Petter Selasky if (err)
13018e6e287fSHans Petter Selasky goto err_destroy_sq;
13028e6e287fSHans Petter Selasky
13038e6e287fSHans Petter Selasky
1304b633e08cSHans Petter Selasky err = create_raw_packet_qp_tir(dev, rq, tdn, pd);
13058e6e287fSHans Petter Selasky if (err)
13068e6e287fSHans Petter Selasky goto err_destroy_rq;
13078e6e287fSHans Petter Selasky }
13088e6e287fSHans Petter Selasky
13098e6e287fSHans Petter Selasky qp->trans_qp.base.mqp.qpn = qp->sq.wqe_cnt ? sq->base.mqp.qpn :
13108e6e287fSHans Petter Selasky rq->base.mqp.qpn;
13118e6e287fSHans Petter Selasky
13128e6e287fSHans Petter Selasky return 0;
13138e6e287fSHans Petter Selasky
13148e6e287fSHans Petter Selasky err_destroy_rq:
13158e6e287fSHans Petter Selasky destroy_raw_packet_qp_rq(dev, rq);
13168e6e287fSHans Petter Selasky err_destroy_sq:
13178e6e287fSHans Petter Selasky if (!qp->sq.wqe_cnt)
13188e6e287fSHans Petter Selasky return err;
13198e6e287fSHans Petter Selasky destroy_raw_packet_qp_sq(dev, sq);
13208e6e287fSHans Petter Selasky err_destroy_tis:
1321b633e08cSHans Petter Selasky destroy_raw_packet_qp_tis(dev, sq, pd);
13228e6e287fSHans Petter Selasky
13238e6e287fSHans Petter Selasky return err;
13248e6e287fSHans Petter Selasky }
13258e6e287fSHans Petter Selasky
destroy_raw_packet_qp(struct mlx5_ib_dev * dev,struct mlx5_ib_qp * qp)13268e6e287fSHans Petter Selasky static void destroy_raw_packet_qp(struct mlx5_ib_dev *dev,
13278e6e287fSHans Petter Selasky struct mlx5_ib_qp *qp)
13288e6e287fSHans Petter Selasky {
13298e6e287fSHans Petter Selasky struct mlx5_ib_raw_packet_qp *raw_packet_qp = &qp->raw_packet_qp;
13308e6e287fSHans Petter Selasky struct mlx5_ib_sq *sq = &raw_packet_qp->sq;
13318e6e287fSHans Petter Selasky struct mlx5_ib_rq *rq = &raw_packet_qp->rq;
13328e6e287fSHans Petter Selasky
13338e6e287fSHans Petter Selasky if (qp->rq.wqe_cnt) {
1334b633e08cSHans Petter Selasky destroy_raw_packet_qp_tir(dev, rq, qp->ibqp.pd);
13358e6e287fSHans Petter Selasky destroy_raw_packet_qp_rq(dev, rq);
13368e6e287fSHans Petter Selasky }
13378e6e287fSHans Petter Selasky
13388e6e287fSHans Petter Selasky if (qp->sq.wqe_cnt) {
13398e6e287fSHans Petter Selasky destroy_raw_packet_qp_sq(dev, sq);
1340b633e08cSHans Petter Selasky destroy_raw_packet_qp_tis(dev, sq, qp->ibqp.pd);
13418e6e287fSHans Petter Selasky }
13428e6e287fSHans Petter Selasky }
13438e6e287fSHans Petter Selasky
raw_packet_qp_copy_info(struct mlx5_ib_qp * qp,struct mlx5_ib_raw_packet_qp * raw_packet_qp)13448e6e287fSHans Petter Selasky static void raw_packet_qp_copy_info(struct mlx5_ib_qp *qp,
13458e6e287fSHans Petter Selasky struct mlx5_ib_raw_packet_qp *raw_packet_qp)
13468e6e287fSHans Petter Selasky {
13478e6e287fSHans Petter Selasky struct mlx5_ib_sq *sq = &raw_packet_qp->sq;
13488e6e287fSHans Petter Selasky struct mlx5_ib_rq *rq = &raw_packet_qp->rq;
13498e6e287fSHans Petter Selasky
13508e6e287fSHans Petter Selasky sq->sq = &qp->sq;
13518e6e287fSHans Petter Selasky rq->rq = &qp->rq;
13528e6e287fSHans Petter Selasky sq->doorbell = &qp->db;
13538e6e287fSHans Petter Selasky rq->doorbell = &qp->db;
13548e6e287fSHans Petter Selasky }
13558e6e287fSHans Petter Selasky
destroy_rss_raw_qp_tir(struct mlx5_ib_dev * dev,struct mlx5_ib_qp * qp)13568e6e287fSHans Petter Selasky static void destroy_rss_raw_qp_tir(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp)
13578e6e287fSHans Petter Selasky {
1358b633e08cSHans Petter Selasky mlx5_core_destroy_tir(dev->mdev, qp->rss_qp.tirn,
1359b633e08cSHans Petter Selasky to_mpd(qp->ibqp.pd)->uid);
13608e6e287fSHans Petter Selasky }
13618e6e287fSHans Petter Selasky
create_rss_raw_qp_tir(struct mlx5_ib_dev * dev,struct mlx5_ib_qp * qp,struct ib_pd * pd,struct ib_qp_init_attr * init_attr,struct ib_udata * udata)13628e6e287fSHans Petter Selasky static int create_rss_raw_qp_tir(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
13638e6e287fSHans Petter Selasky struct ib_pd *pd,
13648e6e287fSHans Petter Selasky struct ib_qp_init_attr *init_attr,
13658e6e287fSHans Petter Selasky struct ib_udata *udata)
13668e6e287fSHans Petter Selasky {
13678e6e287fSHans Petter Selasky struct ib_uobject *uobj = pd->uobject;
13688e6e287fSHans Petter Selasky struct ib_ucontext *ucontext = uobj->context;
13698e6e287fSHans Petter Selasky struct mlx5_ib_ucontext *mucontext = to_mucontext(ucontext);
13708e6e287fSHans Petter Selasky struct mlx5_ib_create_qp_resp resp = {};
13718e6e287fSHans Petter Selasky int inlen;
13728e6e287fSHans Petter Selasky int err;
13738e6e287fSHans Petter Selasky u32 *in;
13748e6e287fSHans Petter Selasky void *tirc;
13758e6e287fSHans Petter Selasky void *hfso;
13768e6e287fSHans Petter Selasky u32 selected_fields = 0;
13778e6e287fSHans Petter Selasky size_t min_resp_len;
13788e6e287fSHans Petter Selasky u32 tdn = mucontext->tdn;
13798e6e287fSHans Petter Selasky struct mlx5_ib_create_qp_rss ucmd = {};
13808e6e287fSHans Petter Selasky size_t required_cmd_sz;
13818e6e287fSHans Petter Selasky
13828e6e287fSHans Petter Selasky if (init_attr->qp_type != IB_QPT_RAW_PACKET)
13838e6e287fSHans Petter Selasky return -EOPNOTSUPP;
13848e6e287fSHans Petter Selasky
13858e6e287fSHans Petter Selasky if (init_attr->create_flags || init_attr->send_cq)
13868e6e287fSHans Petter Selasky return -EINVAL;
13878e6e287fSHans Petter Selasky
1388f8f5b459SHans Petter Selasky min_resp_len = offsetof(typeof(resp), bfreg_index) + sizeof(resp.bfreg_index);
13898e6e287fSHans Petter Selasky if (udata->outlen < min_resp_len)
13908e6e287fSHans Petter Selasky return -EINVAL;
13918e6e287fSHans Petter Selasky
13928e6e287fSHans Petter Selasky required_cmd_sz = offsetof(typeof(ucmd), reserved1) + sizeof(ucmd.reserved1);
13938e6e287fSHans Petter Selasky if (udata->inlen < required_cmd_sz) {
13948e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "invalid inlen\n");
13958e6e287fSHans Petter Selasky return -EINVAL;
13968e6e287fSHans Petter Selasky }
13978e6e287fSHans Petter Selasky
13988e6e287fSHans Petter Selasky if (udata->inlen > sizeof(ucmd) &&
13998e6e287fSHans Petter Selasky !ib_is_udata_cleared(udata, sizeof(ucmd),
14008e6e287fSHans Petter Selasky udata->inlen - sizeof(ucmd))) {
14018e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "inlen is not supported\n");
14028e6e287fSHans Petter Selasky return -EOPNOTSUPP;
14038e6e287fSHans Petter Selasky }
14048e6e287fSHans Petter Selasky
14058e6e287fSHans Petter Selasky if (ib_copy_from_udata(&ucmd, udata, min(sizeof(ucmd), udata->inlen))) {
14068e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "copy failed\n");
14078e6e287fSHans Petter Selasky return -EFAULT;
14088e6e287fSHans Petter Selasky }
14098e6e287fSHans Petter Selasky
14108e6e287fSHans Petter Selasky if (ucmd.comp_mask) {
14118e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "invalid comp mask\n");
14128e6e287fSHans Petter Selasky return -EOPNOTSUPP;
14138e6e287fSHans Petter Selasky }
14148e6e287fSHans Petter Selasky
14158e6e287fSHans Petter Selasky if (memchr_inv(ucmd.reserved, 0, sizeof(ucmd.reserved)) || ucmd.reserved1) {
14168e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "invalid reserved\n");
14178e6e287fSHans Petter Selasky return -EOPNOTSUPP;
14188e6e287fSHans Petter Selasky }
14198e6e287fSHans Petter Selasky
14208e6e287fSHans Petter Selasky err = ib_copy_to_udata(udata, &resp, min_resp_len);
14218e6e287fSHans Petter Selasky if (err) {
14228e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "copy failed\n");
14238e6e287fSHans Petter Selasky return -EINVAL;
14248e6e287fSHans Petter Selasky }
14258e6e287fSHans Petter Selasky
14268e6e287fSHans Petter Selasky inlen = MLX5_ST_SZ_BYTES(create_tir_in);
14278e6e287fSHans Petter Selasky in = mlx5_vzalloc(inlen);
14288e6e287fSHans Petter Selasky if (!in)
14298e6e287fSHans Petter Selasky return -ENOMEM;
14308e6e287fSHans Petter Selasky
1431b633e08cSHans Petter Selasky MLX5_SET(create_tir_in, in, uid, to_mpd(pd)->uid);
14328e6e287fSHans Petter Selasky tirc = MLX5_ADDR_OF(create_tir_in, in, tir_context);
14338e6e287fSHans Petter Selasky MLX5_SET(tirc, tirc, disp_type,
14348e6e287fSHans Petter Selasky MLX5_TIRC_DISP_TYPE_INDIRECT);
14358e6e287fSHans Petter Selasky MLX5_SET(tirc, tirc, indirect_table,
14368e6e287fSHans Petter Selasky init_attr->rwq_ind_tbl->ind_tbl_num);
14378e6e287fSHans Petter Selasky MLX5_SET(tirc, tirc, transport_domain, tdn);
14388e6e287fSHans Petter Selasky
14398e6e287fSHans Petter Selasky hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_outer);
14408e6e287fSHans Petter Selasky switch (ucmd.rx_hash_function) {
14418e6e287fSHans Petter Selasky case MLX5_RX_HASH_FUNC_TOEPLITZ:
14428e6e287fSHans Petter Selasky {
14438e6e287fSHans Petter Selasky void *rss_key = MLX5_ADDR_OF(tirc, tirc, rx_hash_toeplitz_key);
14448e6e287fSHans Petter Selasky size_t len = MLX5_FLD_SZ_BYTES(tirc, rx_hash_toeplitz_key);
14458e6e287fSHans Petter Selasky
14468e6e287fSHans Petter Selasky if (len != ucmd.rx_key_len) {
14478e6e287fSHans Petter Selasky err = -EINVAL;
14488e6e287fSHans Petter Selasky goto err;
14498e6e287fSHans Petter Selasky }
14508e6e287fSHans Petter Selasky
14518e6e287fSHans Petter Selasky MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FUNC_TOEPLITZ);
14528e6e287fSHans Petter Selasky memcpy(rss_key, ucmd.rx_hash_key, len);
14538e6e287fSHans Petter Selasky break;
14548e6e287fSHans Petter Selasky }
145512515907SHans Petter Selasky default:
14568e6e287fSHans Petter Selasky err = -EOPNOTSUPP;
14578e6e287fSHans Petter Selasky goto err;
145812515907SHans Petter Selasky }
145912515907SHans Petter Selasky
14608e6e287fSHans Petter Selasky if (!ucmd.rx_hash_fields_mask) {
14618e6e287fSHans Petter Selasky /* special case when this TIR serves as steering entry without hashing */
14628e6e287fSHans Petter Selasky if (!init_attr->rwq_ind_tbl->log_ind_tbl_size)
14638e6e287fSHans Petter Selasky goto create_tir;
14648e6e287fSHans Petter Selasky err = -EINVAL;
14658e6e287fSHans Petter Selasky goto err;
14668e6e287fSHans Petter Selasky }
14678e6e287fSHans Petter Selasky
14688e6e287fSHans Petter Selasky if (((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_IPV4) ||
14698e6e287fSHans Petter Selasky (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_IPV4)) &&
14708e6e287fSHans Petter Selasky ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_IPV6) ||
14718e6e287fSHans Petter Selasky (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_IPV6))) {
14728e6e287fSHans Petter Selasky err = -EINVAL;
14738e6e287fSHans Petter Selasky goto err;
14748e6e287fSHans Petter Selasky }
14758e6e287fSHans Petter Selasky
14768e6e287fSHans Petter Selasky /* If none of IPV4 & IPV6 SRC/DST was set - this bit field is ignored */
14778e6e287fSHans Petter Selasky if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_IPV4) ||
14788e6e287fSHans Petter Selasky (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_IPV4))
14798e6e287fSHans Petter Selasky MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
14808e6e287fSHans Petter Selasky MLX5_L3_PROT_TYPE_IPV4);
14818e6e287fSHans Petter Selasky else if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_IPV6) ||
14828e6e287fSHans Petter Selasky (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_IPV6))
14838e6e287fSHans Petter Selasky MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
14848e6e287fSHans Petter Selasky MLX5_L3_PROT_TYPE_IPV6);
14858e6e287fSHans Petter Selasky
14868e6e287fSHans Petter Selasky if (((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_PORT_TCP) ||
14878e6e287fSHans Petter Selasky (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_PORT_TCP)) &&
14888e6e287fSHans Petter Selasky ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_PORT_UDP) ||
14898e6e287fSHans Petter Selasky (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_PORT_UDP))) {
14908e6e287fSHans Petter Selasky err = -EINVAL;
14918e6e287fSHans Petter Selasky goto err;
14928e6e287fSHans Petter Selasky }
14938e6e287fSHans Petter Selasky
14948e6e287fSHans Petter Selasky /* If none of TCP & UDP SRC/DST was set - this bit field is ignored */
14958e6e287fSHans Petter Selasky if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_PORT_TCP) ||
14968e6e287fSHans Petter Selasky (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_PORT_TCP))
14978e6e287fSHans Petter Selasky MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
14988e6e287fSHans Petter Selasky MLX5_L4_PROT_TYPE_TCP);
14998e6e287fSHans Petter Selasky else if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_PORT_UDP) ||
15008e6e287fSHans Petter Selasky (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_PORT_UDP))
15018e6e287fSHans Petter Selasky MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
15028e6e287fSHans Petter Selasky MLX5_L4_PROT_TYPE_UDP);
15038e6e287fSHans Petter Selasky
15048e6e287fSHans Petter Selasky if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_IPV4) ||
15058e6e287fSHans Petter Selasky (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_IPV6))
15068e6e287fSHans Petter Selasky selected_fields |= MLX5_HASH_FIELD_SEL_SRC_IP;
15078e6e287fSHans Petter Selasky
15088e6e287fSHans Petter Selasky if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_IPV4) ||
15098e6e287fSHans Petter Selasky (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_IPV6))
15108e6e287fSHans Petter Selasky selected_fields |= MLX5_HASH_FIELD_SEL_DST_IP;
15118e6e287fSHans Petter Selasky
15128e6e287fSHans Petter Selasky if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_PORT_TCP) ||
15138e6e287fSHans Petter Selasky (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_PORT_UDP))
15148e6e287fSHans Petter Selasky selected_fields |= MLX5_HASH_FIELD_SEL_L4_SPORT;
15158e6e287fSHans Petter Selasky
15168e6e287fSHans Petter Selasky if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_PORT_TCP) ||
15178e6e287fSHans Petter Selasky (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_PORT_UDP))
15188e6e287fSHans Petter Selasky selected_fields |= MLX5_HASH_FIELD_SEL_L4_DPORT;
15198e6e287fSHans Petter Selasky
15208e6e287fSHans Petter Selasky MLX5_SET(rx_hash_field_select, hfso, selected_fields, selected_fields);
15218e6e287fSHans Petter Selasky
15228e6e287fSHans Petter Selasky create_tir:
15238e6e287fSHans Petter Selasky err = mlx5_core_create_tir(dev->mdev, in, inlen, &qp->rss_qp.tirn);
15248e6e287fSHans Petter Selasky
15258e6e287fSHans Petter Selasky if (err)
15268e6e287fSHans Petter Selasky goto err;
15278e6e287fSHans Petter Selasky
15288e6e287fSHans Petter Selasky kvfree(in);
15298e6e287fSHans Petter Selasky /* qpn is reserved for that QP */
15308e6e287fSHans Petter Selasky qp->trans_qp.base.mqp.qpn = 0;
15318e6e287fSHans Petter Selasky qp->flags |= MLX5_IB_QP_RSS;
15328e6e287fSHans Petter Selasky return 0;
15338e6e287fSHans Petter Selasky
15348e6e287fSHans Petter Selasky err:
15358e6e287fSHans Petter Selasky kvfree(in);
15368e6e287fSHans Petter Selasky return err;
15378e6e287fSHans Petter Selasky }
153812515907SHans Petter Selasky
atomic_size_to_mode(int size_mask)1539cf88b86eSHans Petter Selasky static int atomic_size_to_mode(int size_mask)
1540cf88b86eSHans Petter Selasky {
1541cf88b86eSHans Petter Selasky /* driver does not support atomic_size > 256B
1542cf88b86eSHans Petter Selasky * and does not know how to translate bigger sizes
1543cf88b86eSHans Petter Selasky */
1544cf88b86eSHans Petter Selasky int supported_size_mask = size_mask & 0x1ff;
1545cf88b86eSHans Petter Selasky int log_max_size;
1546cf88b86eSHans Petter Selasky
1547cf88b86eSHans Petter Selasky if (!supported_size_mask)
1548cf88b86eSHans Petter Selasky return -EOPNOTSUPP;
1549cf88b86eSHans Petter Selasky
1550cf88b86eSHans Petter Selasky log_max_size = __fls(supported_size_mask);
1551cf88b86eSHans Petter Selasky
1552cf88b86eSHans Petter Selasky if (log_max_size > 3)
1553cf88b86eSHans Petter Selasky return log_max_size;
1554cf88b86eSHans Petter Selasky
1555cf88b86eSHans Petter Selasky return MLX5_ATOMIC_MODE_8B;
1556cf88b86eSHans Petter Selasky }
1557cf88b86eSHans Petter Selasky
get_atomic_mode(struct mlx5_ib_dev * dev,enum ib_qp_type qp_type)1558cf88b86eSHans Petter Selasky static int get_atomic_mode(struct mlx5_ib_dev *dev,
1559cf88b86eSHans Petter Selasky enum ib_qp_type qp_type)
1560cf88b86eSHans Petter Selasky {
1561cf88b86eSHans Petter Selasky u8 atomic_operations = MLX5_CAP_ATOMIC(dev->mdev, atomic_operations);
1562cf88b86eSHans Petter Selasky u8 atomic = MLX5_CAP_GEN(dev->mdev, atomic);
1563cf88b86eSHans Petter Selasky int atomic_mode = -EOPNOTSUPP;
1564cf88b86eSHans Petter Selasky int atomic_size_mask;
1565cf88b86eSHans Petter Selasky
1566cf88b86eSHans Petter Selasky if (!atomic)
1567cf88b86eSHans Petter Selasky return -EOPNOTSUPP;
1568cf88b86eSHans Petter Selasky
1569cf88b86eSHans Petter Selasky if (qp_type == MLX5_IB_QPT_DCT)
1570cf88b86eSHans Petter Selasky atomic_size_mask = MLX5_CAP_ATOMIC(dev->mdev, atomic_size_dc);
1571cf88b86eSHans Petter Selasky else
1572cf88b86eSHans Petter Selasky atomic_size_mask = MLX5_CAP_ATOMIC(dev->mdev, atomic_size_qp);
1573cf88b86eSHans Petter Selasky
1574cf88b86eSHans Petter Selasky if ((atomic_operations & MLX5_ATOMIC_OPS_MASKED_CMP_SWAP) ||
1575cf88b86eSHans Petter Selasky (atomic_operations & MLX5_ATOMIC_OPS_MASKED_FETCH_ADD))
1576cf88b86eSHans Petter Selasky atomic_mode = atomic_size_to_mode(atomic_size_mask);
1577cf88b86eSHans Petter Selasky
1578cf88b86eSHans Petter Selasky if (atomic_mode <= 0 &&
1579cf88b86eSHans Petter Selasky (atomic_operations & MLX5_ATOMIC_OPS_CMP_SWAP &&
1580cf88b86eSHans Petter Selasky atomic_operations & MLX5_ATOMIC_OPS_FETCH_ADD))
1581cf88b86eSHans Petter Selasky atomic_mode = MLX5_ATOMIC_MODE_IB_COMP;
1582cf88b86eSHans Petter Selasky
1583cf88b86eSHans Petter Selasky return atomic_mode;
1584cf88b86eSHans Petter Selasky }
1585cf88b86eSHans Petter Selasky
create_qp_common(struct mlx5_ib_dev * dev,struct ib_pd * pd,struct ib_qp_init_attr * init_attr,struct ib_udata * udata,struct mlx5_ib_qp * qp)158612515907SHans Petter Selasky static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
158712515907SHans Petter Selasky struct ib_qp_init_attr *init_attr,
158812515907SHans Petter Selasky struct ib_udata *udata, struct mlx5_ib_qp *qp)
158912515907SHans Petter Selasky {
159012515907SHans Petter Selasky struct mlx5_ib_resources *devr = &dev->devr;
15918e6e287fSHans Petter Selasky int inlen = MLX5_ST_SZ_BYTES(create_qp_in);
159212515907SHans Petter Selasky struct mlx5_core_dev *mdev = dev->mdev;
15938e6e287fSHans Petter Selasky struct mlx5_ib_create_qp_resp resp;
159412515907SHans Petter Selasky struct mlx5_ib_cq *send_cq;
159512515907SHans Petter Selasky struct mlx5_ib_cq *recv_cq;
159612515907SHans Petter Selasky unsigned long flags;
15978e6e287fSHans Petter Selasky u32 uidx = MLX5_IB_DEFAULT_UIDX;
15988e6e287fSHans Petter Selasky struct mlx5_ib_create_qp ucmd;
15998e6e287fSHans Petter Selasky struct mlx5_ib_qp_base *base;
160012515907SHans Petter Selasky void *qpc;
16018e6e287fSHans Petter Selasky u32 *in;
16028e6e287fSHans Petter Selasky int err;
16038e6e287fSHans Petter Selasky
16048e6e287fSHans Petter Selasky base = init_attr->qp_type == IB_QPT_RAW_PACKET ?
16058e6e287fSHans Petter Selasky &qp->raw_packet_qp.rq.base :
16068e6e287fSHans Petter Selasky &qp->trans_qp.base;
16078e6e287fSHans Petter Selasky
16088e6e287fSHans Petter Selasky if (init_attr->qp_type != IB_QPT_RAW_PACKET)
16098e6e287fSHans Petter Selasky mlx5_ib_odp_create_qp(qp);
161012515907SHans Petter Selasky
161112515907SHans Petter Selasky mutex_init(&qp->mutex);
161212515907SHans Petter Selasky spin_lock_init(&qp->sq.lock);
161312515907SHans Petter Selasky spin_lock_init(&qp->rq.lock);
161412515907SHans Petter Selasky
16158e6e287fSHans Petter Selasky if (init_attr->rwq_ind_tbl) {
16168e6e287fSHans Petter Selasky if (!udata)
16178e6e287fSHans Petter Selasky return -ENOSYS;
16188e6e287fSHans Petter Selasky
16198e6e287fSHans Petter Selasky err = create_rss_raw_qp_tir(dev, qp, pd, init_attr, udata);
16208e6e287fSHans Petter Selasky return err;
16218e6e287fSHans Petter Selasky }
16228e6e287fSHans Petter Selasky
162312515907SHans Petter Selasky if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) {
162412515907SHans Petter Selasky if (!MLX5_CAP_GEN(mdev, block_lb_mc)) {
16258e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "block multicast loopback isn't supported\n");
162612515907SHans Petter Selasky return -EINVAL;
162712515907SHans Petter Selasky } else {
162812515907SHans Petter Selasky qp->flags |= MLX5_IB_QP_BLOCK_MULTICAST_LOOPBACK;
162912515907SHans Petter Selasky }
163012515907SHans Petter Selasky }
163112515907SHans Petter Selasky
16328e6e287fSHans Petter Selasky if (init_attr->create_flags &
16338e6e287fSHans Petter Selasky (IB_QP_CREATE_CROSS_CHANNEL |
16348e6e287fSHans Petter Selasky IB_QP_CREATE_MANAGED_SEND |
16358e6e287fSHans Petter Selasky IB_QP_CREATE_MANAGED_RECV)) {
16368e6e287fSHans Petter Selasky if (!MLX5_CAP_GEN(mdev, cd)) {
16378e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "cross-channel isn't supported\n");
16388e6e287fSHans Petter Selasky return -EINVAL;
16398e6e287fSHans Petter Selasky }
16408e6e287fSHans Petter Selasky if (init_attr->create_flags & IB_QP_CREATE_CROSS_CHANNEL)
16418e6e287fSHans Petter Selasky qp->flags |= MLX5_IB_QP_CROSS_CHANNEL;
16428e6e287fSHans Petter Selasky if (init_attr->create_flags & IB_QP_CREATE_MANAGED_SEND)
16438e6e287fSHans Petter Selasky qp->flags |= MLX5_IB_QP_MANAGED_SEND;
16448e6e287fSHans Petter Selasky if (init_attr->create_flags & IB_QP_CREATE_MANAGED_RECV)
16458e6e287fSHans Petter Selasky qp->flags |= MLX5_IB_QP_MANAGED_RECV;
16468e6e287fSHans Petter Selasky }
16478e6e287fSHans Petter Selasky
16488e6e287fSHans Petter Selasky if (init_attr->qp_type == IB_QPT_UD &&
16498e6e287fSHans Petter Selasky (init_attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO))
16508e6e287fSHans Petter Selasky if (!MLX5_CAP_GEN(mdev, ipoib_ipoib_offloads)) {
16518e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "ipoib UD lso qp isn't supported\n");
16528e6e287fSHans Petter Selasky return -EOPNOTSUPP;
16538e6e287fSHans Petter Selasky }
16548e6e287fSHans Petter Selasky
16558e6e287fSHans Petter Selasky if (init_attr->create_flags & IB_QP_CREATE_SCATTER_FCS) {
16568e6e287fSHans Petter Selasky if (init_attr->qp_type != IB_QPT_RAW_PACKET) {
16578e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "Scatter FCS is supported only for Raw Packet QPs");
16588e6e287fSHans Petter Selasky return -EOPNOTSUPP;
16598e6e287fSHans Petter Selasky }
16608e6e287fSHans Petter Selasky if (!MLX5_CAP_GEN(dev->mdev, eth_net_offloads) ||
16618e6e287fSHans Petter Selasky !MLX5_CAP_ETH(dev->mdev, scatter_fcs)) {
16628e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "Scatter FCS isn't supported\n");
16638e6e287fSHans Petter Selasky return -EOPNOTSUPP;
16648e6e287fSHans Petter Selasky }
16658e6e287fSHans Petter Selasky qp->flags |= MLX5_IB_QP_CAP_SCATTER_FCS;
16668e6e287fSHans Petter Selasky }
16678e6e287fSHans Petter Selasky
166812515907SHans Petter Selasky if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
166912515907SHans Petter Selasky qp->sq_signal_bits = MLX5_WQE_CTRL_CQ_UPDATE;
167012515907SHans Petter Selasky
167112515907SHans Petter Selasky if (pd && pd->uobject) {
16728e6e287fSHans Petter Selasky if (ib_copy_from_udata(&ucmd, udata, sizeof(ucmd))) {
16738e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "copy failed\n");
16748e6e287fSHans Petter Selasky return -EFAULT;
167512515907SHans Petter Selasky }
16768e6e287fSHans Petter Selasky
16778e6e287fSHans Petter Selasky err = get_qp_user_index(to_mucontext(pd->uobject->context),
16788e6e287fSHans Petter Selasky &ucmd, udata->inlen, &uidx);
16798e6e287fSHans Petter Selasky if (err)
168012515907SHans Petter Selasky return err;
168112515907SHans Petter Selasky
168212515907SHans Petter Selasky qp->wq_sig = !!(ucmd.flags & MLX5_QP_FLAG_SIGNATURE);
16838e6e287fSHans Petter Selasky qp->scat_cqe = !!(ucmd.flags & MLX5_QP_FLAG_SCATTER_CQE);
168412515907SHans Petter Selasky } else {
16858e6e287fSHans Petter Selasky qp->wq_sig = !!wq_signature;
168612515907SHans Petter Selasky }
168712515907SHans Petter Selasky
168812515907SHans Petter Selasky qp->has_rq = qp_has_rq(init_attr);
168912515907SHans Petter Selasky err = set_rq_size(dev, &init_attr->cap, qp->has_rq,
16908e6e287fSHans Petter Selasky qp, (pd && pd->uobject) ? &ucmd : NULL);
169112515907SHans Petter Selasky if (err) {
16928e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "err %d\n", err);
169312515907SHans Petter Selasky return err;
169412515907SHans Petter Selasky }
169512515907SHans Petter Selasky
169612515907SHans Petter Selasky if (pd) {
169712515907SHans Petter Selasky if (pd->uobject) {
169812515907SHans Petter Selasky __u32 max_wqes =
169912515907SHans Petter Selasky 1 << MLX5_CAP_GEN(mdev, log_max_qp_sz);
170012515907SHans Petter Selasky mlx5_ib_dbg(dev, "requested sq_wqe_count (%d)\n", ucmd.sq_wqe_count);
170112515907SHans Petter Selasky if (ucmd.rq_wqe_shift != qp->rq.wqe_shift ||
170212515907SHans Petter Selasky ucmd.rq_wqe_count != qp->rq.wqe_cnt) {
17038e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "invalid rq params\n");
170412515907SHans Petter Selasky return -EINVAL;
170512515907SHans Petter Selasky }
170612515907SHans Petter Selasky if (ucmd.sq_wqe_count > max_wqes) {
17078e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "requested sq_wqe_count (%d) > max allowed (%d)\n",
170812515907SHans Petter Selasky ucmd.sq_wqe_count, max_wqes);
170912515907SHans Petter Selasky return -EINVAL;
171012515907SHans Petter Selasky }
17118e6e287fSHans Petter Selasky if (init_attr->create_flags &
1712f8f5b459SHans Petter Selasky MLX5_IB_QP_CREATE_SQPN_QP1) {
17138e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "user-space is not allowed to create UD QPs spoofing as QP1\n");
171412515907SHans Petter Selasky return -EINVAL;
171512515907SHans Petter Selasky }
17168e6e287fSHans Petter Selasky err = create_user_qp(dev, pd, qp, udata, init_attr, &in,
17178e6e287fSHans Petter Selasky &resp, &inlen, base);
171812515907SHans Petter Selasky if (err)
17198e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "err %d\n", err);
17208e6e287fSHans Petter Selasky } else {
17218e6e287fSHans Petter Selasky err = create_kernel_qp(dev, init_attr, qp, &in, &inlen,
17228e6e287fSHans Petter Selasky base);
17238e6e287fSHans Petter Selasky if (err)
17248e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "err %d\n", err);
172512515907SHans Petter Selasky }
172612515907SHans Petter Selasky
172712515907SHans Petter Selasky if (err)
172812515907SHans Petter Selasky return err;
172912515907SHans Petter Selasky } else {
17308e6e287fSHans Petter Selasky in = mlx5_vzalloc(inlen);
173112515907SHans Petter Selasky if (!in)
173212515907SHans Petter Selasky return -ENOMEM;
173312515907SHans Petter Selasky
173412515907SHans Petter Selasky qp->create_type = MLX5_QP_EMPTY;
173512515907SHans Petter Selasky }
173612515907SHans Petter Selasky
173712515907SHans Petter Selasky if (is_sqp(init_attr->qp_type))
173812515907SHans Petter Selasky qp->port = init_attr->port_num;
173912515907SHans Petter Selasky
17408e6e287fSHans Petter Selasky qpc = MLX5_ADDR_OF(create_qp_in, in, qpc);
174112515907SHans Petter Selasky
17428e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, st, to_mlx5_st(init_attr->qp_type));
17438e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, pm_state, MLX5_QP_PM_MIGRATED);
17448e6e287fSHans Petter Selasky
17458e6e287fSHans Petter Selasky if (init_attr->qp_type != MLX5_IB_QPT_REG_UMR)
17468e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, pd, to_mpd(pd ? pd : devr->p0)->pdn);
17478e6e287fSHans Petter Selasky else
17488e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, latency_sensitive, 1);
17498e6e287fSHans Petter Selasky
175012515907SHans Petter Selasky
175112515907SHans Petter Selasky if (qp->wq_sig)
17528e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, wq_signature, 1);
175312515907SHans Petter Selasky
175412515907SHans Petter Selasky if (qp->flags & MLX5_IB_QP_BLOCK_MULTICAST_LOOPBACK)
17558e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, block_lb_mc, 1);
175612515907SHans Petter Selasky
17578e6e287fSHans Petter Selasky if (qp->flags & MLX5_IB_QP_CROSS_CHANNEL)
17588e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, cd_master, 1);
17598e6e287fSHans Petter Selasky if (qp->flags & MLX5_IB_QP_MANAGED_SEND)
17608e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, cd_slave_send, 1);
17618e6e287fSHans Petter Selasky if (qp->flags & MLX5_IB_QP_MANAGED_RECV)
17628e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, cd_slave_receive, 1);
176312515907SHans Petter Selasky
176412515907SHans Petter Selasky if (qp->scat_cqe && is_connected(init_attr->qp_type)) {
176512515907SHans Petter Selasky int rcqe_sz;
176612515907SHans Petter Selasky int scqe_sz;
176712515907SHans Petter Selasky
176812515907SHans Petter Selasky rcqe_sz = mlx5_ib_get_cqe_size(dev, init_attr->recv_cq);
176912515907SHans Petter Selasky scqe_sz = mlx5_ib_get_cqe_size(dev, init_attr->send_cq);
177012515907SHans Petter Selasky
17718e6e287fSHans Petter Selasky if (rcqe_sz == 128)
17728e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, cs_res, MLX5_RES_SCAT_DATA64_CQE);
177312515907SHans Petter Selasky else
17748e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, cs_res, MLX5_RES_SCAT_DATA32_CQE);
17758e6e287fSHans Petter Selasky
17768e6e287fSHans Petter Selasky if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) {
17778e6e287fSHans Petter Selasky if (scqe_sz == 128)
17788e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, cs_req, MLX5_REQ_SCAT_DATA64_CQE);
17798e6e287fSHans Petter Selasky else
17808e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, cs_req, MLX5_REQ_SCAT_DATA32_CQE);
178112515907SHans Petter Selasky }
178212515907SHans Petter Selasky }
178312515907SHans Petter Selasky
178412515907SHans Petter Selasky if (qp->rq.wqe_cnt) {
17858e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, log_rq_stride, qp->rq.wqe_shift - 4);
17868e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, log_rq_size, ilog2(qp->rq.wqe_cnt));
178712515907SHans Petter Selasky }
178812515907SHans Petter Selasky
17894fb0a74eSHans Petter Selasky if (init_attr->qp_type != IB_QPT_RAW_PACKET)
17904fb0a74eSHans Petter Selasky MLX5_SET(qpc, qpc, ts_format, mlx5_get_qp_default_ts(dev->mdev));
17914fb0a74eSHans Petter Selasky
17928e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, rq_type, get_rx_type(qp, init_attr));
179312515907SHans Petter Selasky
179412515907SHans Petter Selasky if (qp->sq.wqe_cnt)
17958e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, log_sq_size, ilog2(qp->sq.wqe_cnt));
179612515907SHans Petter Selasky else
17978e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, no_sq, 1);
179812515907SHans Petter Selasky
179912515907SHans Petter Selasky /* Set default resources */
180012515907SHans Petter Selasky switch (init_attr->qp_type) {
180112515907SHans Petter Selasky case IB_QPT_XRC_TGT:
18028e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, cqn_rcv, to_mcq(devr->c0)->mcq.cqn);
18038e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, cqn_snd, to_mcq(devr->c0)->mcq.cqn);
18048e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, srqn_rmpn, to_msrq(devr->s0)->msrq.srqn);
18058e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, xrcd, to_mxrcd(init_attr->xrcd)->xrcdn);
180612515907SHans Petter Selasky break;
180712515907SHans Petter Selasky case IB_QPT_XRC_INI:
18088e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, cqn_rcv, to_mcq(devr->c0)->mcq.cqn);
18098e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, xrcd, to_mxrcd(devr->x1)->xrcdn);
18108e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, srqn_rmpn, to_msrq(devr->s0)->msrq.srqn);
181112515907SHans Petter Selasky break;
181212515907SHans Petter Selasky default:
181312515907SHans Petter Selasky if (init_attr->srq) {
18148e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, xrcd, to_mxrcd(devr->x0)->xrcdn);
18158e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, srqn_rmpn, to_msrq(init_attr->srq)->msrq.srqn);
181612515907SHans Petter Selasky } else {
18178e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, xrcd, to_mxrcd(devr->x1)->xrcdn);
18188e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, srqn_rmpn, to_msrq(devr->s1)->msrq.srqn);
181912515907SHans Petter Selasky }
182012515907SHans Petter Selasky }
182112515907SHans Petter Selasky
182212515907SHans Petter Selasky if (init_attr->send_cq)
18238e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, cqn_snd, to_mcq(init_attr->send_cq)->mcq.cqn);
182412515907SHans Petter Selasky
182512515907SHans Petter Selasky if (init_attr->recv_cq)
18268e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, cqn_rcv, to_mcq(init_attr->recv_cq)->mcq.cqn);
182712515907SHans Petter Selasky
18288e6e287fSHans Petter Selasky MLX5_SET64(qpc, qpc, dbr_addr, qp->db.dma);
182912515907SHans Petter Selasky
183012515907SHans Petter Selasky /* 0xffffff means we ask to work with cqe version 0 */
18318e6e287fSHans Petter Selasky if (MLX5_CAP_GEN(mdev, cqe_version) == MLX5_CQE_VERSION_V1)
183212515907SHans Petter Selasky MLX5_SET(qpc, qpc, user_index, uidx);
18338e6e287fSHans Petter Selasky
18348e6e287fSHans Petter Selasky /* we use IB_QP_CREATE_IPOIB_UD_LSO to indicates ipoib qp */
18358e6e287fSHans Petter Selasky if (init_attr->qp_type == IB_QPT_UD &&
18368e6e287fSHans Petter Selasky (init_attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO)) {
18378e6e287fSHans Petter Selasky MLX5_SET(qpc, qpc, ulp_stateless_offload_mode, 1);
18388e6e287fSHans Petter Selasky qp->flags |= MLX5_IB_QP_LSO;
183912515907SHans Petter Selasky }
184012515907SHans Petter Selasky
184112515907SHans Petter Selasky if (init_attr->qp_type == IB_QPT_RAW_PACKET) {
18428e6e287fSHans Petter Selasky qp->raw_packet_qp.sq.ubuffer.buf_addr = ucmd.sq_buf_addr;
18438e6e287fSHans Petter Selasky raw_packet_qp_copy_info(qp, &qp->raw_packet_qp);
18448e6e287fSHans Petter Selasky err = create_raw_packet_qp(dev, qp, in, pd);
184512515907SHans Petter Selasky } else {
1846788333d9SHans Petter Selasky err = mlx5_core_create_qp(dev->mdev, &base->mqp, in, inlen);
184712515907SHans Petter Selasky }
184812515907SHans Petter Selasky
184912515907SHans Petter Selasky if (err) {
18508e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "create qp failed\n");
185112515907SHans Petter Selasky goto err_create;
185212515907SHans Petter Selasky }
185312515907SHans Petter Selasky
185412515907SHans Petter Selasky kvfree(in);
18558e6e287fSHans Petter Selasky
18568e6e287fSHans Petter Selasky base->container_mibqp = qp;
18578e6e287fSHans Petter Selasky base->mqp.event = mlx5_ib_qp_event;
185812515907SHans Petter Selasky
185912515907SHans Petter Selasky get_cqs(init_attr->qp_type, init_attr->send_cq, init_attr->recv_cq,
186012515907SHans Petter Selasky &send_cq, &recv_cq);
186112515907SHans Petter Selasky spin_lock_irqsave(&dev->reset_flow_resource_lock, flags);
186212515907SHans Petter Selasky mlx5_ib_lock_cqs(send_cq, recv_cq);
186312515907SHans Petter Selasky /* Maintain device to QPs access, needed for further handling via reset
186412515907SHans Petter Selasky * flow
186512515907SHans Petter Selasky */
186612515907SHans Petter Selasky list_add_tail(&qp->qps_list, &dev->qp_list);
186712515907SHans Petter Selasky /* Maintain CQ to QPs access, needed for further handling via reset flow
186812515907SHans Petter Selasky */
186912515907SHans Petter Selasky if (send_cq)
187012515907SHans Petter Selasky list_add_tail(&qp->cq_send_list, &send_cq->list_send_qp);
187112515907SHans Petter Selasky if (recv_cq)
187212515907SHans Petter Selasky list_add_tail(&qp->cq_recv_list, &recv_cq->list_recv_qp);
187312515907SHans Petter Selasky mlx5_ib_unlock_cqs(send_cq, recv_cq);
187412515907SHans Petter Selasky spin_unlock_irqrestore(&dev->reset_flow_resource_lock, flags);
187512515907SHans Petter Selasky
187612515907SHans Petter Selasky return 0;
187712515907SHans Petter Selasky
187812515907SHans Petter Selasky err_create:
187912515907SHans Petter Selasky if (qp->create_type == MLX5_QP_USER)
1880b633e08cSHans Petter Selasky destroy_qp_user(dev, pd, qp, base, udata);
188112515907SHans Petter Selasky else if (qp->create_type == MLX5_QP_KERNEL)
188212515907SHans Petter Selasky destroy_qp_kernel(dev, qp);
188312515907SHans Petter Selasky
188412515907SHans Petter Selasky kvfree(in);
188512515907SHans Petter Selasky return err;
188612515907SHans Petter Selasky }
188712515907SHans Petter Selasky
mlx5_ib_lock_cqs(struct mlx5_ib_cq * send_cq,struct mlx5_ib_cq * recv_cq)188812515907SHans Petter Selasky static void mlx5_ib_lock_cqs(struct mlx5_ib_cq *send_cq, struct mlx5_ib_cq *recv_cq)
188912515907SHans Petter Selasky __acquires(&send_cq->lock) __acquires(&recv_cq->lock)
189012515907SHans Petter Selasky {
189112515907SHans Petter Selasky if (send_cq) {
189212515907SHans Petter Selasky if (recv_cq) {
189312515907SHans Petter Selasky if (send_cq->mcq.cqn < recv_cq->mcq.cqn) {
189412515907SHans Petter Selasky spin_lock(&send_cq->lock);
189512515907SHans Petter Selasky spin_lock_nested(&recv_cq->lock,
189612515907SHans Petter Selasky SINGLE_DEPTH_NESTING);
189712515907SHans Petter Selasky } else if (send_cq->mcq.cqn == recv_cq->mcq.cqn) {
189812515907SHans Petter Selasky spin_lock(&send_cq->lock);
189912515907SHans Petter Selasky __acquire(&recv_cq->lock);
190012515907SHans Petter Selasky } else {
190112515907SHans Petter Selasky spin_lock(&recv_cq->lock);
190212515907SHans Petter Selasky spin_lock_nested(&send_cq->lock,
190312515907SHans Petter Selasky SINGLE_DEPTH_NESTING);
190412515907SHans Petter Selasky }
190512515907SHans Petter Selasky } else {
190612515907SHans Petter Selasky spin_lock(&send_cq->lock);
190712515907SHans Petter Selasky __acquire(&recv_cq->lock);
190812515907SHans Petter Selasky }
190912515907SHans Petter Selasky } else if (recv_cq) {
191012515907SHans Petter Selasky spin_lock(&recv_cq->lock);
191112515907SHans Petter Selasky __acquire(&send_cq->lock);
191212515907SHans Petter Selasky } else {
191312515907SHans Petter Selasky __acquire(&send_cq->lock);
191412515907SHans Petter Selasky __acquire(&recv_cq->lock);
191512515907SHans Petter Selasky }
191612515907SHans Petter Selasky }
191712515907SHans Petter Selasky
mlx5_ib_unlock_cqs(struct mlx5_ib_cq * send_cq,struct mlx5_ib_cq * recv_cq)191812515907SHans Petter Selasky static void mlx5_ib_unlock_cqs(struct mlx5_ib_cq *send_cq, struct mlx5_ib_cq *recv_cq)
191912515907SHans Petter Selasky __releases(&send_cq->lock) __releases(&recv_cq->lock)
192012515907SHans Petter Selasky {
192112515907SHans Petter Selasky if (send_cq) {
192212515907SHans Petter Selasky if (recv_cq) {
192312515907SHans Petter Selasky if (send_cq->mcq.cqn < recv_cq->mcq.cqn) {
192412515907SHans Petter Selasky spin_unlock(&recv_cq->lock);
192512515907SHans Petter Selasky spin_unlock(&send_cq->lock);
192612515907SHans Petter Selasky } else if (send_cq->mcq.cqn == recv_cq->mcq.cqn) {
192712515907SHans Petter Selasky __release(&recv_cq->lock);
192812515907SHans Petter Selasky spin_unlock(&send_cq->lock);
192912515907SHans Petter Selasky } else {
193012515907SHans Petter Selasky spin_unlock(&send_cq->lock);
193112515907SHans Petter Selasky spin_unlock(&recv_cq->lock);
193212515907SHans Petter Selasky }
193312515907SHans Petter Selasky } else {
193412515907SHans Petter Selasky __release(&recv_cq->lock);
193512515907SHans Petter Selasky spin_unlock(&send_cq->lock);
193612515907SHans Petter Selasky }
193712515907SHans Petter Selasky } else if (recv_cq) {
193812515907SHans Petter Selasky __release(&send_cq->lock);
193912515907SHans Petter Selasky spin_unlock(&recv_cq->lock);
194012515907SHans Petter Selasky } else {
194112515907SHans Petter Selasky __release(&recv_cq->lock);
194212515907SHans Petter Selasky __release(&send_cq->lock);
194312515907SHans Petter Selasky }
194412515907SHans Petter Selasky }
194512515907SHans Petter Selasky
get_pd(struct mlx5_ib_qp * qp)194612515907SHans Petter Selasky static struct mlx5_ib_pd *get_pd(struct mlx5_ib_qp *qp)
194712515907SHans Petter Selasky {
194812515907SHans Petter Selasky return to_mpd(qp->ibqp.pd);
194912515907SHans Petter Selasky }
195012515907SHans Petter Selasky
get_cqs(enum ib_qp_type qp_type,struct ib_cq * ib_send_cq,struct ib_cq * ib_recv_cq,struct mlx5_ib_cq ** send_cq,struct mlx5_ib_cq ** recv_cq)19518e6e287fSHans Petter Selasky static void get_cqs(enum ib_qp_type qp_type,
19528e6e287fSHans Petter Selasky struct ib_cq *ib_send_cq, struct ib_cq *ib_recv_cq,
19538e6e287fSHans Petter Selasky struct mlx5_ib_cq **send_cq, struct mlx5_ib_cq **recv_cq)
19548e6e287fSHans Petter Selasky {
19558e6e287fSHans Petter Selasky switch (qp_type) {
19568e6e287fSHans Petter Selasky case IB_QPT_XRC_TGT:
19578e6e287fSHans Petter Selasky *send_cq = NULL;
19588e6e287fSHans Petter Selasky *recv_cq = NULL;
19598e6e287fSHans Petter Selasky break;
19608e6e287fSHans Petter Selasky case MLX5_IB_QPT_REG_UMR:
19618e6e287fSHans Petter Selasky case IB_QPT_XRC_INI:
19628e6e287fSHans Petter Selasky *send_cq = ib_send_cq ? to_mcq(ib_send_cq) : NULL;
19638e6e287fSHans Petter Selasky *recv_cq = NULL;
19648e6e287fSHans Petter Selasky break;
19658e6e287fSHans Petter Selasky
19668e6e287fSHans Petter Selasky case IB_QPT_SMI:
19678e6e287fSHans Petter Selasky case MLX5_IB_QPT_HW_GSI:
19688e6e287fSHans Petter Selasky case IB_QPT_RC:
19698e6e287fSHans Petter Selasky case IB_QPT_UC:
19708e6e287fSHans Petter Selasky case IB_QPT_UD:
19718e6e287fSHans Petter Selasky case IB_QPT_RAW_IPV6:
19728e6e287fSHans Petter Selasky case IB_QPT_RAW_ETHERTYPE:
19738e6e287fSHans Petter Selasky case IB_QPT_RAW_PACKET:
19748e6e287fSHans Petter Selasky *send_cq = ib_send_cq ? to_mcq(ib_send_cq) : NULL;
19758e6e287fSHans Petter Selasky *recv_cq = ib_recv_cq ? to_mcq(ib_recv_cq) : NULL;
19768e6e287fSHans Petter Selasky break;
19778e6e287fSHans Petter Selasky
19788e6e287fSHans Petter Selasky case IB_QPT_MAX:
19798e6e287fSHans Petter Selasky default:
19808e6e287fSHans Petter Selasky *send_cq = NULL;
19818e6e287fSHans Petter Selasky *recv_cq = NULL;
19828e6e287fSHans Petter Selasky break;
19838e6e287fSHans Petter Selasky }
19848e6e287fSHans Petter Selasky }
19858e6e287fSHans Petter Selasky
19868e6e287fSHans Petter Selasky static int modify_raw_packet_qp(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
19878e6e287fSHans Petter Selasky const struct mlx5_modify_raw_qp_param *raw_qp_param,
19888e6e287fSHans Petter Selasky u8 lag_tx_affinity);
19898e6e287fSHans Petter Selasky
destroy_qp_common(struct mlx5_ib_dev * dev,struct mlx5_ib_qp * qp,struct ib_udata * udata)1990b633e08cSHans Petter Selasky static void destroy_qp_common(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
1991b633e08cSHans Petter Selasky struct ib_udata *udata)
199212515907SHans Petter Selasky {
199312515907SHans Petter Selasky struct mlx5_ib_cq *send_cq, *recv_cq;
19948e6e287fSHans Petter Selasky struct mlx5_ib_qp_base *base = &qp->trans_qp.base;
199512515907SHans Petter Selasky unsigned long flags;
199612515907SHans Petter Selasky int err;
199712515907SHans Petter Selasky
19988e6e287fSHans Petter Selasky if (qp->ibqp.rwq_ind_tbl) {
19998e6e287fSHans Petter Selasky destroy_rss_raw_qp_tir(dev, qp);
200012515907SHans Petter Selasky return;
20018e6e287fSHans Petter Selasky }
20028e6e287fSHans Petter Selasky
20038e6e287fSHans Petter Selasky base = qp->ibqp.qp_type == IB_QPT_RAW_PACKET ?
20048e6e287fSHans Petter Selasky &qp->raw_packet_qp.rq.base :
20058e6e287fSHans Petter Selasky &qp->trans_qp.base;
200612515907SHans Petter Selasky
200712515907SHans Petter Selasky if (qp->state != IB_QPS_RESET) {
200812515907SHans Petter Selasky if (qp->ibqp.qp_type != IB_QPT_RAW_PACKET) {
20098e6e287fSHans Petter Selasky mlx5_ib_qp_disable_pagefaults(qp);
20108e6e287fSHans Petter Selasky err = mlx5_core_qp_modify(dev->mdev,
2011788333d9SHans Petter Selasky MLX5_CMD_OP_2RST_QP, 0,
2012788333d9SHans Petter Selasky NULL, &base->mqp);
20138e6e287fSHans Petter Selasky } else {
20148e6e287fSHans Petter Selasky struct mlx5_modify_raw_qp_param raw_qp_param = {
20158e6e287fSHans Petter Selasky .operation = MLX5_CMD_OP_2RST_QP
20168e6e287fSHans Petter Selasky };
20178e6e287fSHans Petter Selasky
20188e6e287fSHans Petter Selasky err = modify_raw_packet_qp(dev, qp, &raw_qp_param, 0);
20198e6e287fSHans Petter Selasky }
20208e6e287fSHans Petter Selasky if (err)
20218e6e287fSHans Petter Selasky mlx5_ib_warn(dev, "mlx5_ib: modify QP 0x%06x to RESET failed\n",
20228e6e287fSHans Petter Selasky base->mqp.qpn);
202312515907SHans Petter Selasky }
202412515907SHans Petter Selasky
202512515907SHans Petter Selasky get_cqs(qp->ibqp.qp_type, qp->ibqp.send_cq, qp->ibqp.recv_cq,
202612515907SHans Petter Selasky &send_cq, &recv_cq);
202712515907SHans Petter Selasky
202812515907SHans Petter Selasky spin_lock_irqsave(&dev->reset_flow_resource_lock, flags);
202912515907SHans Petter Selasky mlx5_ib_lock_cqs(send_cq, recv_cq);
203012515907SHans Petter Selasky /* del from lists under both locks above to protect reset flow paths */
203112515907SHans Petter Selasky list_del(&qp->qps_list);
203212515907SHans Petter Selasky if (send_cq)
203312515907SHans Petter Selasky list_del(&qp->cq_send_list);
203412515907SHans Petter Selasky
203512515907SHans Petter Selasky if (recv_cq)
203612515907SHans Petter Selasky list_del(&qp->cq_recv_list);
203712515907SHans Petter Selasky
203812515907SHans Petter Selasky if (qp->create_type == MLX5_QP_KERNEL) {
20398e6e287fSHans Petter Selasky __mlx5_ib_cq_clean(recv_cq, base->mqp.qpn,
204012515907SHans Petter Selasky qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
204112515907SHans Petter Selasky if (send_cq != recv_cq)
20428e6e287fSHans Petter Selasky __mlx5_ib_cq_clean(send_cq, base->mqp.qpn,
20438e6e287fSHans Petter Selasky NULL);
204412515907SHans Petter Selasky }
204512515907SHans Petter Selasky mlx5_ib_unlock_cqs(send_cq, recv_cq);
204612515907SHans Petter Selasky spin_unlock_irqrestore(&dev->reset_flow_resource_lock, flags);
204712515907SHans Petter Selasky
204812515907SHans Petter Selasky if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET) {
20498e6e287fSHans Petter Selasky destroy_raw_packet_qp(dev, qp);
205012515907SHans Petter Selasky } else {
20518e6e287fSHans Petter Selasky err = mlx5_core_destroy_qp(dev->mdev, &base->mqp);
205212515907SHans Petter Selasky if (err)
205312515907SHans Petter Selasky mlx5_ib_warn(dev, "failed to destroy QP 0x%x\n",
20548e6e287fSHans Petter Selasky base->mqp.qpn);
205512515907SHans Petter Selasky }
205612515907SHans Petter Selasky
205712515907SHans Petter Selasky if (qp->create_type == MLX5_QP_KERNEL)
205812515907SHans Petter Selasky destroy_qp_kernel(dev, qp);
205912515907SHans Petter Selasky else if (qp->create_type == MLX5_QP_USER)
2060b633e08cSHans Petter Selasky destroy_qp_user(dev, &get_pd(qp)->ibpd, qp, base, udata);
206112515907SHans Petter Selasky }
206212515907SHans Petter Selasky
ib_qp_type_str(enum ib_qp_type type)206312515907SHans Petter Selasky static const char *ib_qp_type_str(enum ib_qp_type type)
206412515907SHans Petter Selasky {
206512515907SHans Petter Selasky switch (type) {
206612515907SHans Petter Selasky case IB_QPT_SMI:
206712515907SHans Petter Selasky return "IB_QPT_SMI";
206812515907SHans Petter Selasky case IB_QPT_GSI:
206912515907SHans Petter Selasky return "IB_QPT_GSI";
207012515907SHans Petter Selasky case IB_QPT_RC:
207112515907SHans Petter Selasky return "IB_QPT_RC";
207212515907SHans Petter Selasky case IB_QPT_UC:
207312515907SHans Petter Selasky return "IB_QPT_UC";
207412515907SHans Petter Selasky case IB_QPT_UD:
207512515907SHans Petter Selasky return "IB_QPT_UD";
207612515907SHans Petter Selasky case IB_QPT_RAW_IPV6:
207712515907SHans Petter Selasky return "IB_QPT_RAW_IPV6";
207812515907SHans Petter Selasky case IB_QPT_RAW_ETHERTYPE:
207912515907SHans Petter Selasky return "IB_QPT_RAW_ETHERTYPE";
208012515907SHans Petter Selasky case IB_QPT_XRC_INI:
208112515907SHans Petter Selasky return "IB_QPT_XRC_INI";
208212515907SHans Petter Selasky case IB_QPT_XRC_TGT:
208312515907SHans Petter Selasky return "IB_QPT_XRC_TGT";
208412515907SHans Petter Selasky case IB_QPT_RAW_PACKET:
208512515907SHans Petter Selasky return "IB_QPT_RAW_PACKET";
20868e6e287fSHans Petter Selasky case MLX5_IB_QPT_REG_UMR:
20878e6e287fSHans Petter Selasky return "MLX5_IB_QPT_REG_UMR";
208812515907SHans Petter Selasky case IB_QPT_MAX:
208912515907SHans Petter Selasky default:
209012515907SHans Petter Selasky return "Invalid QP type";
209112515907SHans Petter Selasky }
209212515907SHans Petter Selasky }
209312515907SHans Petter Selasky
mlx5_ib_create_qp(struct ib_pd * pd,struct ib_qp_init_attr * init_attr,struct ib_udata * udata)209412515907SHans Petter Selasky struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd,
209512515907SHans Petter Selasky struct ib_qp_init_attr *init_attr,
209612515907SHans Petter Selasky struct ib_udata *udata)
209712515907SHans Petter Selasky {
209812515907SHans Petter Selasky struct mlx5_ib_dev *dev;
209912515907SHans Petter Selasky struct mlx5_ib_qp *qp;
210012515907SHans Petter Selasky u16 xrcdn = 0;
210112515907SHans Petter Selasky int err;
210212515907SHans Petter Selasky
210312515907SHans Petter Selasky if (pd) {
210412515907SHans Petter Selasky dev = to_mdev(pd->device);
21058e6e287fSHans Petter Selasky
21068e6e287fSHans Petter Selasky if (init_attr->qp_type == IB_QPT_RAW_PACKET) {
21078e6e287fSHans Petter Selasky if (!pd->uobject) {
21088e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "Raw Packet QP is not supported for kernel consumers\n");
21098e6e287fSHans Petter Selasky return ERR_PTR(-EINVAL);
21108e6e287fSHans Petter Selasky } else if (!to_mucontext(pd->uobject->context)->cqe_version) {
21118e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "Raw Packet QP is only supported for CQE version > 0\n");
21128e6e287fSHans Petter Selasky return ERR_PTR(-EINVAL);
21138e6e287fSHans Petter Selasky }
21148e6e287fSHans Petter Selasky }
211512515907SHans Petter Selasky } else {
211612515907SHans Petter Selasky /* being cautious here */
21178e6e287fSHans Petter Selasky if (init_attr->qp_type != IB_QPT_XRC_TGT &&
21188e6e287fSHans Petter Selasky init_attr->qp_type != MLX5_IB_QPT_REG_UMR) {
21198e6e287fSHans Petter Selasky pr_warn("%s: no PD for transport %s\n", __func__,
21208e6e287fSHans Petter Selasky ib_qp_type_str(init_attr->qp_type));
212112515907SHans Petter Selasky return ERR_PTR(-EINVAL);
212212515907SHans Petter Selasky }
212312515907SHans Petter Selasky dev = to_mdev(to_mxrcd(init_attr->xrcd)->ibxrcd.device);
212412515907SHans Petter Selasky }
212512515907SHans Petter Selasky
212612515907SHans Petter Selasky switch (init_attr->qp_type) {
212712515907SHans Petter Selasky case IB_QPT_XRC_TGT:
212812515907SHans Petter Selasky case IB_QPT_XRC_INI:
212912515907SHans Petter Selasky if (!MLX5_CAP_GEN(dev->mdev, xrc)) {
21308e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "XRC not supported\n");
213112515907SHans Petter Selasky return ERR_PTR(-ENOSYS);
213212515907SHans Petter Selasky }
213312515907SHans Petter Selasky init_attr->recv_cq = NULL;
213412515907SHans Petter Selasky if (init_attr->qp_type == IB_QPT_XRC_TGT) {
213512515907SHans Petter Selasky xrcdn = to_mxrcd(init_attr->xrcd)->xrcdn;
213612515907SHans Petter Selasky init_attr->send_cq = NULL;
213712515907SHans Petter Selasky }
213812515907SHans Petter Selasky
213912515907SHans Petter Selasky /* fall through */
21408e6e287fSHans Petter Selasky case IB_QPT_RAW_PACKET:
214112515907SHans Petter Selasky case IB_QPT_RC:
214212515907SHans Petter Selasky case IB_QPT_UC:
214312515907SHans Petter Selasky case IB_QPT_UD:
214412515907SHans Petter Selasky case IB_QPT_SMI:
21458e6e287fSHans Petter Selasky case MLX5_IB_QPT_HW_GSI:
21468e6e287fSHans Petter Selasky case MLX5_IB_QPT_REG_UMR:
214712515907SHans Petter Selasky qp = kzalloc(sizeof(*qp), GFP_KERNEL);
214812515907SHans Petter Selasky if (!qp)
214912515907SHans Petter Selasky return ERR_PTR(-ENOMEM);
215012515907SHans Petter Selasky
215112515907SHans Petter Selasky err = create_qp_common(dev, pd, init_attr, udata, qp);
215212515907SHans Petter Selasky if (err) {
21538e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "create_qp_common failed\n");
215412515907SHans Petter Selasky kfree(qp);
215512515907SHans Petter Selasky return ERR_PTR(err);
215612515907SHans Petter Selasky }
215712515907SHans Petter Selasky
215812515907SHans Petter Selasky if (is_qp0(init_attr->qp_type))
215912515907SHans Petter Selasky qp->ibqp.qp_num = 0;
216012515907SHans Petter Selasky else if (is_qp1(init_attr->qp_type))
216112515907SHans Petter Selasky qp->ibqp.qp_num = 1;
216212515907SHans Petter Selasky else
21638e6e287fSHans Petter Selasky qp->ibqp.qp_num = qp->trans_qp.base.mqp.qpn;
216412515907SHans Petter Selasky
216512515907SHans Petter Selasky mlx5_ib_dbg(dev, "ib qpnum 0x%x, mlx qpn 0x%x, rcqn 0x%x, scqn 0x%x\n",
21668e6e287fSHans Petter Selasky qp->ibqp.qp_num, qp->trans_qp.base.mqp.qpn,
21678e6e287fSHans Petter Selasky init_attr->recv_cq ? to_mcq(init_attr->recv_cq)->mcq.cqn : -1,
21688e6e287fSHans Petter Selasky init_attr->send_cq ? to_mcq(init_attr->send_cq)->mcq.cqn : -1);
216912515907SHans Petter Selasky
21708e6e287fSHans Petter Selasky qp->trans_qp.xrcdn = xrcdn;
217112515907SHans Petter Selasky
217212515907SHans Petter Selasky break;
217312515907SHans Petter Selasky
21748e6e287fSHans Petter Selasky case IB_QPT_GSI:
21758e6e287fSHans Petter Selasky return mlx5_ib_gsi_create_qp(pd, init_attr);
21768e6e287fSHans Petter Selasky
217712515907SHans Petter Selasky case IB_QPT_RAW_IPV6:
21788e6e287fSHans Petter Selasky case IB_QPT_RAW_ETHERTYPE:
217912515907SHans Petter Selasky case IB_QPT_MAX:
218012515907SHans Petter Selasky default:
21818e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "unsupported qp type %d\n",
218212515907SHans Petter Selasky init_attr->qp_type);
218312515907SHans Petter Selasky /* Don't support raw QPs */
218412515907SHans Petter Selasky return ERR_PTR(-EINVAL);
218512515907SHans Petter Selasky }
218612515907SHans Petter Selasky
218712515907SHans Petter Selasky return &qp->ibqp;
218812515907SHans Petter Selasky }
218912515907SHans Petter Selasky
mlx5_ib_destroy_qp(struct ib_qp * qp,struct ib_udata * udata)2190b633e08cSHans Petter Selasky int mlx5_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
219112515907SHans Petter Selasky {
219212515907SHans Petter Selasky struct mlx5_ib_dev *dev = to_mdev(qp->device);
219312515907SHans Petter Selasky struct mlx5_ib_qp *mqp = to_mqp(qp);
219412515907SHans Petter Selasky
21958e6e287fSHans Petter Selasky if (unlikely(qp->qp_type == IB_QPT_GSI))
21968e6e287fSHans Petter Selasky return mlx5_ib_gsi_destroy_qp(qp);
21978e6e287fSHans Petter Selasky
2198b633e08cSHans Petter Selasky destroy_qp_common(dev, mqp, udata);
219912515907SHans Petter Selasky
220012515907SHans Petter Selasky kfree(mqp);
220112515907SHans Petter Selasky
220212515907SHans Petter Selasky return 0;
220312515907SHans Petter Selasky }
220412515907SHans Petter Selasky
to_mlx5_access_flags(struct mlx5_ib_qp * qp,const struct ib_qp_attr * attr,int attr_mask,__be32 * hw_access_flags_be)2205cf88b86eSHans Petter Selasky static int to_mlx5_access_flags(struct mlx5_ib_qp *qp,
2206cf88b86eSHans Petter Selasky const struct ib_qp_attr *attr,
2207cf88b86eSHans Petter Selasky int attr_mask, __be32 *hw_access_flags_be)
220812515907SHans Petter Selasky {
220912515907SHans Petter Selasky u8 dest_rd_atomic;
2210cf88b86eSHans Petter Selasky u32 access_flags, hw_access_flags = 0;
2211cf88b86eSHans Petter Selasky
2212cf88b86eSHans Petter Selasky struct mlx5_ib_dev *dev = to_mdev(qp->ibqp.device);
221312515907SHans Petter Selasky
221412515907SHans Petter Selasky if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
221512515907SHans Petter Selasky dest_rd_atomic = attr->max_dest_rd_atomic;
221612515907SHans Petter Selasky else
22178e6e287fSHans Petter Selasky dest_rd_atomic = qp->trans_qp.resp_depth;
221812515907SHans Petter Selasky
221912515907SHans Petter Selasky if (attr_mask & IB_QP_ACCESS_FLAGS)
222012515907SHans Petter Selasky access_flags = attr->qp_access_flags;
222112515907SHans Petter Selasky else
22228e6e287fSHans Petter Selasky access_flags = qp->trans_qp.atomic_rd_en;
222312515907SHans Petter Selasky
222412515907SHans Petter Selasky if (!dest_rd_atomic)
222512515907SHans Petter Selasky access_flags &= IB_ACCESS_REMOTE_WRITE;
222612515907SHans Petter Selasky
222712515907SHans Petter Selasky if (access_flags & IB_ACCESS_REMOTE_READ)
222812515907SHans Petter Selasky hw_access_flags |= MLX5_QP_BIT_RRE;
2229cf88b86eSHans Petter Selasky if (access_flags & IB_ACCESS_REMOTE_ATOMIC) {
2230cf88b86eSHans Petter Selasky int atomic_mode;
2231cf88b86eSHans Petter Selasky
2232cf88b86eSHans Petter Selasky atomic_mode = get_atomic_mode(dev, qp->ibqp.qp_type);
2233cf88b86eSHans Petter Selasky if (atomic_mode < 0)
2234cf88b86eSHans Petter Selasky return -EOPNOTSUPP;
2235cf88b86eSHans Petter Selasky
2236cf88b86eSHans Petter Selasky hw_access_flags |= MLX5_QP_BIT_RAE;
2237cf88b86eSHans Petter Selasky hw_access_flags |= atomic_mode << MLX5_ATOMIC_MODE_OFF;
2238cf88b86eSHans Petter Selasky }
2239cf88b86eSHans Petter Selasky
224012515907SHans Petter Selasky if (access_flags & IB_ACCESS_REMOTE_WRITE)
224112515907SHans Petter Selasky hw_access_flags |= MLX5_QP_BIT_RWE;
224212515907SHans Petter Selasky
2243cf88b86eSHans Petter Selasky *hw_access_flags_be = cpu_to_be32(hw_access_flags);
2244cf88b86eSHans Petter Selasky
2245cf88b86eSHans Petter Selasky return 0;
224612515907SHans Petter Selasky }
224712515907SHans Petter Selasky
224812515907SHans Petter Selasky enum {
224912515907SHans Petter Selasky MLX5_PATH_FLAG_FL = 1 << 0,
225012515907SHans Petter Selasky MLX5_PATH_FLAG_FREE_AR = 1 << 1,
225112515907SHans Petter Selasky MLX5_PATH_FLAG_COUNTER = 1 << 2,
225212515907SHans Petter Selasky };
225312515907SHans Petter Selasky
ib_rate_to_mlx5(struct mlx5_ib_dev * dev,u8 rate)225412515907SHans Petter Selasky static int ib_rate_to_mlx5(struct mlx5_ib_dev *dev, u8 rate)
225512515907SHans Petter Selasky {
225612515907SHans Petter Selasky if (rate == IB_RATE_PORT_CURRENT) {
225712515907SHans Petter Selasky return 0;
225886a39779SHans Petter Selasky } else if (rate < IB_RATE_2_5_GBPS || rate > IB_RATE_600_GBPS) {
225912515907SHans Petter Selasky return -EINVAL;
226012515907SHans Petter Selasky } else {
226112515907SHans Petter Selasky while (rate != IB_RATE_2_5_GBPS &&
226212515907SHans Petter Selasky !(1 << (rate + MLX5_STAT_RATE_OFFSET) &
226312515907SHans Petter Selasky MLX5_CAP_GEN(dev->mdev, stat_rate_support)))
226412515907SHans Petter Selasky --rate;
226512515907SHans Petter Selasky }
226612515907SHans Petter Selasky
226712515907SHans Petter Selasky return rate + MLX5_STAT_RATE_OFFSET;
226812515907SHans Petter Selasky }
226912515907SHans Petter Selasky
modify_raw_packet_eth_prio(struct mlx5_core_dev * dev,struct mlx5_ib_sq * sq,u8 sl,struct ib_pd * pd)22708e6e287fSHans Petter Selasky static int modify_raw_packet_eth_prio(struct mlx5_core_dev *dev,
2271b633e08cSHans Petter Selasky struct mlx5_ib_sq *sq, u8 sl,
2272b633e08cSHans Petter Selasky struct ib_pd *pd)
22738e6e287fSHans Petter Selasky {
22748e6e287fSHans Petter Selasky void *in;
22758e6e287fSHans Petter Selasky void *tisc;
22768e6e287fSHans Petter Selasky int inlen;
22778e6e287fSHans Petter Selasky int err;
22788e6e287fSHans Petter Selasky
22798e6e287fSHans Petter Selasky inlen = MLX5_ST_SZ_BYTES(modify_tis_in);
22808e6e287fSHans Petter Selasky in = mlx5_vzalloc(inlen);
22818e6e287fSHans Petter Selasky if (!in)
22828e6e287fSHans Petter Selasky return -ENOMEM;
22838e6e287fSHans Petter Selasky
22848e6e287fSHans Petter Selasky MLX5_SET(modify_tis_in, in, bitmask.prio, 1);
2285b633e08cSHans Petter Selasky MLX5_SET(modify_tis_in, in, uid, to_mpd(pd)->uid);
22868e6e287fSHans Petter Selasky
22878e6e287fSHans Petter Selasky tisc = MLX5_ADDR_OF(modify_tis_in, in, ctx);
22888e6e287fSHans Petter Selasky MLX5_SET(tisc, tisc, prio, ((sl & 0x7) << 1));
22898e6e287fSHans Petter Selasky
22908e6e287fSHans Petter Selasky err = mlx5_core_modify_tis(dev, sq->tisn, in, inlen);
22918e6e287fSHans Petter Selasky
22928e6e287fSHans Petter Selasky kvfree(in);
22938e6e287fSHans Petter Selasky
22948e6e287fSHans Petter Selasky return err;
22958e6e287fSHans Petter Selasky }
22968e6e287fSHans Petter Selasky
modify_raw_packet_tx_affinity(struct mlx5_core_dev * dev,struct mlx5_ib_sq * sq,u8 tx_affinity,struct ib_pd * pd)22978e6e287fSHans Petter Selasky static int modify_raw_packet_tx_affinity(struct mlx5_core_dev *dev,
2298b633e08cSHans Petter Selasky struct mlx5_ib_sq *sq, u8 tx_affinity,
2299b633e08cSHans Petter Selasky struct ib_pd *pd)
23008e6e287fSHans Petter Selasky {
23018e6e287fSHans Petter Selasky void *in;
23028e6e287fSHans Petter Selasky void *tisc;
23038e6e287fSHans Petter Selasky int inlen;
23048e6e287fSHans Petter Selasky int err;
23058e6e287fSHans Petter Selasky
23068e6e287fSHans Petter Selasky inlen = MLX5_ST_SZ_BYTES(modify_tis_in);
23078e6e287fSHans Petter Selasky in = mlx5_vzalloc(inlen);
23088e6e287fSHans Petter Selasky if (!in)
23098e6e287fSHans Petter Selasky return -ENOMEM;
23108e6e287fSHans Petter Selasky
23118e6e287fSHans Petter Selasky MLX5_SET(modify_tis_in, in, bitmask.lag_tx_port_affinity, 1);
2312b633e08cSHans Petter Selasky MLX5_SET(modify_tis_in, in, uid, to_mpd(pd)->uid);
23138e6e287fSHans Petter Selasky
23148e6e287fSHans Petter Selasky tisc = MLX5_ADDR_OF(modify_tis_in, in, ctx);
23158e6e287fSHans Petter Selasky MLX5_SET(tisc, tisc, lag_tx_port_affinity, tx_affinity);
23168e6e287fSHans Petter Selasky
23178e6e287fSHans Petter Selasky err = mlx5_core_modify_tis(dev, sq->tisn, in, inlen);
23188e6e287fSHans Petter Selasky
23198e6e287fSHans Petter Selasky kvfree(in);
23208e6e287fSHans Petter Selasky
23218e6e287fSHans Petter Selasky return err;
23228e6e287fSHans Petter Selasky }
23238e6e287fSHans Petter Selasky
mlx5_set_path(struct mlx5_ib_dev * dev,struct mlx5_ib_qp * qp,const struct ib_ah_attr * ah,struct mlx5_qp_path * path,u8 port,int attr_mask,u32 path_flags,const struct ib_qp_attr * attr,bool alt)23248e6e287fSHans Petter Selasky static int mlx5_set_path(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
23258e6e287fSHans Petter Selasky const struct ib_ah_attr *ah,
232612515907SHans Petter Selasky struct mlx5_qp_path *path, u8 port, int attr_mask,
232712515907SHans Petter Selasky u32 path_flags, const struct ib_qp_attr *attr,
23288e6e287fSHans Petter Selasky bool alt)
232912515907SHans Petter Selasky {
23308e6e287fSHans Petter Selasky enum rdma_link_layer ll = rdma_port_get_link_layer(&dev->ib_dev, port);
233112515907SHans Petter Selasky int err;
2332ed0cee0bSHans Petter Selasky enum ib_gid_type gid_type;
233312515907SHans Petter Selasky
23348e6e287fSHans Petter Selasky if (attr_mask & IB_QP_PKEY_INDEX)
23358e6e287fSHans Petter Selasky path->pkey_index = cpu_to_be16(alt ? attr->alt_pkey_index :
23368e6e287fSHans Petter Selasky attr->pkey_index);
23378e6e287fSHans Petter Selasky
23388e6e287fSHans Petter Selasky if (ah->ah_flags & IB_AH_GRH) {
23398e6e287fSHans Petter Selasky if (ah->grh.sgid_index >=
23408e6e287fSHans Petter Selasky dev->mdev->port_caps[port - 1].gid_table_len) {
23418e6e287fSHans Petter Selasky pr_err("sgid_index (%u) too large. max is %d\n",
23428e6e287fSHans Petter Selasky ah->grh.sgid_index,
23438e6e287fSHans Petter Selasky dev->mdev->port_caps[port - 1].gid_table_len);
234412515907SHans Petter Selasky return -EINVAL;
234512515907SHans Petter Selasky }
234612515907SHans Petter Selasky }
234712515907SHans Petter Selasky
234812515907SHans Petter Selasky if (ll == IB_LINK_LAYER_ETHERNET) {
234912515907SHans Petter Selasky if (!(ah->ah_flags & IB_AH_GRH))
235012515907SHans Petter Selasky return -EINVAL;
2351ed0cee0bSHans Petter Selasky err = mlx5_get_roce_gid_type(dev, port, ah->grh.sgid_index,
2352ed0cee0bSHans Petter Selasky &gid_type);
2353ed0cee0bSHans Petter Selasky if (err)
2354ed0cee0bSHans Petter Selasky return err;
235512515907SHans Petter Selasky memcpy(path->rmac, ah->dmac, sizeof(ah->dmac));
235612515907SHans Petter Selasky path->udp_sport = mlx5_get_roce_udp_sport(dev, port,
23578e6e287fSHans Petter Selasky ah->grh.sgid_index);
23588e6e287fSHans Petter Selasky path->dci_cfi_prio_sl = (ah->sl & 0x7) << 4;
2359ed0cee0bSHans Petter Selasky if (gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP)
2360ed0cee0bSHans Petter Selasky path->ecn_dscp = (ah->grh.traffic_class >> 2) & 0x3f;
236112515907SHans Petter Selasky } else {
236212515907SHans Petter Selasky path->fl_free_ar = (path_flags & MLX5_PATH_FLAG_FL) ? 0x80 : 0;
23638e6e287fSHans Petter Selasky path->fl_free_ar |=
23648e6e287fSHans Petter Selasky (path_flags & MLX5_PATH_FLAG_FREE_AR) ? 0x40 : 0;
236512515907SHans Petter Selasky path->rlid = cpu_to_be16(ah->dlid);
23668e6e287fSHans Petter Selasky path->grh_mlid = ah->src_path_bits & 0x7f;
236712515907SHans Petter Selasky if (ah->ah_flags & IB_AH_GRH)
236812515907SHans Petter Selasky path->grh_mlid |= 1 << 7;
236912515907SHans Petter Selasky path->dci_cfi_prio_sl = ah->sl & 0xf;
237012515907SHans Petter Selasky }
237112515907SHans Petter Selasky
237212515907SHans Petter Selasky if (ah->ah_flags & IB_AH_GRH) {
237312515907SHans Petter Selasky path->mgid_index = ah->grh.sgid_index;
237412515907SHans Petter Selasky path->hop_limit = ah->grh.hop_limit;
237512515907SHans Petter Selasky path->tclass_flowlabel =
237612515907SHans Petter Selasky cpu_to_be32((ah->grh.traffic_class << 20) |
237712515907SHans Petter Selasky (ah->grh.flow_label));
237812515907SHans Petter Selasky memcpy(path->rgid, ah->grh.dgid.raw, 16);
237912515907SHans Petter Selasky }
238012515907SHans Petter Selasky
238112515907SHans Petter Selasky err = ib_rate_to_mlx5(dev, ah->static_rate);
238212515907SHans Petter Selasky if (err < 0)
238312515907SHans Petter Selasky return err;
238412515907SHans Petter Selasky path->static_rate = err;
238512515907SHans Petter Selasky path->port = port;
238612515907SHans Petter Selasky
238712515907SHans Petter Selasky if (attr_mask & IB_QP_TIMEOUT)
23888e6e287fSHans Petter Selasky path->ackto_lt = (alt ? attr->alt_timeout : attr->timeout) << 3;
23898e6e287fSHans Petter Selasky
23908e6e287fSHans Petter Selasky if ((qp->ibqp.qp_type == IB_QPT_RAW_PACKET) && qp->sq.wqe_cnt)
23918e6e287fSHans Petter Selasky return modify_raw_packet_eth_prio(dev->mdev,
23928e6e287fSHans Petter Selasky &qp->raw_packet_qp.sq,
2393b633e08cSHans Petter Selasky ah->sl & 0xf, qp->ibqp.pd);
239412515907SHans Petter Selasky
239512515907SHans Petter Selasky return 0;
239612515907SHans Petter Selasky }
239712515907SHans Petter Selasky
239812515907SHans Petter Selasky static enum mlx5_qp_optpar opt_mask[MLX5_QP_NUM_STATE][MLX5_QP_NUM_STATE][MLX5_QP_ST_MAX] = {
239912515907SHans Petter Selasky [MLX5_QP_STATE_INIT] = {
240012515907SHans Petter Selasky [MLX5_QP_STATE_INIT] = {
240112515907SHans Petter Selasky [MLX5_QP_ST_RC] = MLX5_QP_OPTPAR_RRE |
240212515907SHans Petter Selasky MLX5_QP_OPTPAR_RAE |
240312515907SHans Petter Selasky MLX5_QP_OPTPAR_RWE |
240412515907SHans Petter Selasky MLX5_QP_OPTPAR_PKEY_INDEX |
240512515907SHans Petter Selasky MLX5_QP_OPTPAR_PRI_PORT,
240612515907SHans Petter Selasky [MLX5_QP_ST_UC] = MLX5_QP_OPTPAR_RWE |
240712515907SHans Petter Selasky MLX5_QP_OPTPAR_PKEY_INDEX |
240812515907SHans Petter Selasky MLX5_QP_OPTPAR_PRI_PORT,
240912515907SHans Petter Selasky [MLX5_QP_ST_UD] = MLX5_QP_OPTPAR_PKEY_INDEX |
241012515907SHans Petter Selasky MLX5_QP_OPTPAR_Q_KEY |
241112515907SHans Petter Selasky MLX5_QP_OPTPAR_PRI_PORT,
241212515907SHans Petter Selasky },
241312515907SHans Petter Selasky [MLX5_QP_STATE_RTR] = {
241412515907SHans Petter Selasky [MLX5_QP_ST_RC] = MLX5_QP_OPTPAR_ALT_ADDR_PATH |
241512515907SHans Petter Selasky MLX5_QP_OPTPAR_RRE |
241612515907SHans Petter Selasky MLX5_QP_OPTPAR_RAE |
241712515907SHans Petter Selasky MLX5_QP_OPTPAR_RWE |
241812515907SHans Petter Selasky MLX5_QP_OPTPAR_PKEY_INDEX,
241912515907SHans Petter Selasky [MLX5_QP_ST_UC] = MLX5_QP_OPTPAR_ALT_ADDR_PATH |
242012515907SHans Petter Selasky MLX5_QP_OPTPAR_RWE |
242112515907SHans Petter Selasky MLX5_QP_OPTPAR_PKEY_INDEX,
242212515907SHans Petter Selasky [MLX5_QP_ST_UD] = MLX5_QP_OPTPAR_PKEY_INDEX |
242312515907SHans Petter Selasky MLX5_QP_OPTPAR_Q_KEY,
242412515907SHans Petter Selasky [MLX5_QP_ST_MLX] = MLX5_QP_OPTPAR_PKEY_INDEX |
242512515907SHans Petter Selasky MLX5_QP_OPTPAR_Q_KEY,
242612515907SHans Petter Selasky [MLX5_QP_ST_XRC] = MLX5_QP_OPTPAR_ALT_ADDR_PATH |
242712515907SHans Petter Selasky MLX5_QP_OPTPAR_RRE |
242812515907SHans Petter Selasky MLX5_QP_OPTPAR_RAE |
242912515907SHans Petter Selasky MLX5_QP_OPTPAR_RWE |
243012515907SHans Petter Selasky MLX5_QP_OPTPAR_PKEY_INDEX,
243112515907SHans Petter Selasky },
243212515907SHans Petter Selasky },
243312515907SHans Petter Selasky [MLX5_QP_STATE_RTR] = {
243412515907SHans Petter Selasky [MLX5_QP_STATE_RTS] = {
243512515907SHans Petter Selasky [MLX5_QP_ST_RC] = MLX5_QP_OPTPAR_ALT_ADDR_PATH |
243612515907SHans Petter Selasky MLX5_QP_OPTPAR_RRE |
243712515907SHans Petter Selasky MLX5_QP_OPTPAR_RAE |
243812515907SHans Petter Selasky MLX5_QP_OPTPAR_RWE |
243912515907SHans Petter Selasky MLX5_QP_OPTPAR_PM_STATE |
244012515907SHans Petter Selasky MLX5_QP_OPTPAR_RNR_TIMEOUT,
244112515907SHans Petter Selasky [MLX5_QP_ST_UC] = MLX5_QP_OPTPAR_ALT_ADDR_PATH |
244212515907SHans Petter Selasky MLX5_QP_OPTPAR_RWE |
244312515907SHans Petter Selasky MLX5_QP_OPTPAR_PM_STATE,
244412515907SHans Petter Selasky [MLX5_QP_ST_UD] = MLX5_QP_OPTPAR_Q_KEY,
244512515907SHans Petter Selasky },
244612515907SHans Petter Selasky },
244712515907SHans Petter Selasky [MLX5_QP_STATE_RTS] = {
244812515907SHans Petter Selasky [MLX5_QP_STATE_RTS] = {
244912515907SHans Petter Selasky [MLX5_QP_ST_RC] = MLX5_QP_OPTPAR_RRE |
245012515907SHans Petter Selasky MLX5_QP_OPTPAR_RAE |
245112515907SHans Petter Selasky MLX5_QP_OPTPAR_RWE |
245212515907SHans Petter Selasky MLX5_QP_OPTPAR_RNR_TIMEOUT |
245312515907SHans Petter Selasky MLX5_QP_OPTPAR_PM_STATE |
245412515907SHans Petter Selasky MLX5_QP_OPTPAR_ALT_ADDR_PATH,
245512515907SHans Petter Selasky [MLX5_QP_ST_UC] = MLX5_QP_OPTPAR_RWE |
245612515907SHans Petter Selasky MLX5_QP_OPTPAR_PM_STATE |
245712515907SHans Petter Selasky MLX5_QP_OPTPAR_ALT_ADDR_PATH,
245812515907SHans Petter Selasky [MLX5_QP_ST_UD] = MLX5_QP_OPTPAR_Q_KEY |
245912515907SHans Petter Selasky MLX5_QP_OPTPAR_SRQN |
246012515907SHans Petter Selasky MLX5_QP_OPTPAR_CQN_RCV,
246112515907SHans Petter Selasky },
246212515907SHans Petter Selasky },
246312515907SHans Petter Selasky [MLX5_QP_STATE_SQER] = {
246412515907SHans Petter Selasky [MLX5_QP_STATE_RTS] = {
246512515907SHans Petter Selasky [MLX5_QP_ST_UD] = MLX5_QP_OPTPAR_Q_KEY,
246612515907SHans Petter Selasky [MLX5_QP_ST_MLX] = MLX5_QP_OPTPAR_Q_KEY,
246712515907SHans Petter Selasky [MLX5_QP_ST_UC] = MLX5_QP_OPTPAR_RWE,
246812515907SHans Petter Selasky [MLX5_QP_ST_RC] = MLX5_QP_OPTPAR_RNR_TIMEOUT |
246912515907SHans Petter Selasky MLX5_QP_OPTPAR_RWE |
247012515907SHans Petter Selasky MLX5_QP_OPTPAR_RAE |
247112515907SHans Petter Selasky MLX5_QP_OPTPAR_RRE,
247212515907SHans Petter Selasky },
247312515907SHans Petter Selasky },
247412515907SHans Petter Selasky };
247512515907SHans Petter Selasky
ib_nr_to_mlx5_nr(int ib_mask)247612515907SHans Petter Selasky static int ib_nr_to_mlx5_nr(int ib_mask)
247712515907SHans Petter Selasky {
247812515907SHans Petter Selasky switch (ib_mask) {
247912515907SHans Petter Selasky case IB_QP_STATE:
248012515907SHans Petter Selasky return 0;
248112515907SHans Petter Selasky case IB_QP_CUR_STATE:
248212515907SHans Petter Selasky return 0;
248312515907SHans Petter Selasky case IB_QP_EN_SQD_ASYNC_NOTIFY:
248412515907SHans Petter Selasky return 0;
248512515907SHans Petter Selasky case IB_QP_ACCESS_FLAGS:
248612515907SHans Petter Selasky return MLX5_QP_OPTPAR_RWE | MLX5_QP_OPTPAR_RRE |
248712515907SHans Petter Selasky MLX5_QP_OPTPAR_RAE;
248812515907SHans Petter Selasky case IB_QP_PKEY_INDEX:
248912515907SHans Petter Selasky return MLX5_QP_OPTPAR_PKEY_INDEX;
249012515907SHans Petter Selasky case IB_QP_PORT:
249112515907SHans Petter Selasky return MLX5_QP_OPTPAR_PRI_PORT;
249212515907SHans Petter Selasky case IB_QP_QKEY:
249312515907SHans Petter Selasky return MLX5_QP_OPTPAR_Q_KEY;
249412515907SHans Petter Selasky case IB_QP_AV:
249512515907SHans Petter Selasky return MLX5_QP_OPTPAR_PRIMARY_ADDR_PATH |
249612515907SHans Petter Selasky MLX5_QP_OPTPAR_PRI_PORT;
249712515907SHans Petter Selasky case IB_QP_PATH_MTU:
249812515907SHans Petter Selasky return 0;
249912515907SHans Petter Selasky case IB_QP_TIMEOUT:
250012515907SHans Petter Selasky return MLX5_QP_OPTPAR_ACK_TIMEOUT;
250112515907SHans Petter Selasky case IB_QP_RETRY_CNT:
250212515907SHans Petter Selasky return MLX5_QP_OPTPAR_RETRY_COUNT;
250312515907SHans Petter Selasky case IB_QP_RNR_RETRY:
250412515907SHans Petter Selasky return MLX5_QP_OPTPAR_RNR_RETRY;
250512515907SHans Petter Selasky case IB_QP_RQ_PSN:
250612515907SHans Petter Selasky return 0;
250712515907SHans Petter Selasky case IB_QP_MAX_QP_RD_ATOMIC:
250812515907SHans Petter Selasky return MLX5_QP_OPTPAR_SRA_MAX;
250912515907SHans Petter Selasky case IB_QP_ALT_PATH:
251012515907SHans Petter Selasky return MLX5_QP_OPTPAR_ALT_ADDR_PATH;
251112515907SHans Petter Selasky case IB_QP_MIN_RNR_TIMER:
251212515907SHans Petter Selasky return MLX5_QP_OPTPAR_RNR_TIMEOUT;
251312515907SHans Petter Selasky case IB_QP_SQ_PSN:
251412515907SHans Petter Selasky return 0;
251512515907SHans Petter Selasky case IB_QP_MAX_DEST_RD_ATOMIC:
251612515907SHans Petter Selasky return MLX5_QP_OPTPAR_RRA_MAX | MLX5_QP_OPTPAR_RWE |
251712515907SHans Petter Selasky MLX5_QP_OPTPAR_RRE | MLX5_QP_OPTPAR_RAE;
251812515907SHans Petter Selasky case IB_QP_PATH_MIG_STATE:
251912515907SHans Petter Selasky return MLX5_QP_OPTPAR_PM_STATE;
252012515907SHans Petter Selasky case IB_QP_CAP:
252112515907SHans Petter Selasky return 0;
252212515907SHans Petter Selasky case IB_QP_DEST_QPN:
252312515907SHans Petter Selasky return 0;
252412515907SHans Petter Selasky }
252512515907SHans Petter Selasky return 0;
252612515907SHans Petter Selasky }
252712515907SHans Petter Selasky
ib_mask_to_mlx5_opt(int ib_mask)252812515907SHans Petter Selasky static int ib_mask_to_mlx5_opt(int ib_mask)
252912515907SHans Petter Selasky {
253012515907SHans Petter Selasky int result = 0;
253112515907SHans Petter Selasky int i;
253212515907SHans Petter Selasky
253312515907SHans Petter Selasky for (i = 0; i < 8 * sizeof(int); i++) {
253412515907SHans Petter Selasky if ((1 << i) & ib_mask)
253512515907SHans Petter Selasky result |= ib_nr_to_mlx5_nr(1 << i);
253612515907SHans Petter Selasky }
253712515907SHans Petter Selasky
253812515907SHans Petter Selasky return result;
253912515907SHans Petter Selasky }
254012515907SHans Petter Selasky
modify_raw_packet_qp_rq(struct mlx5_ib_dev * dev,struct mlx5_ib_rq * rq,int new_state,const struct mlx5_modify_raw_qp_param * raw_qp_param,struct ib_pd * pd)2541b633e08cSHans Petter Selasky static int modify_raw_packet_qp_rq(
2542b633e08cSHans Petter Selasky struct mlx5_ib_dev *dev, struct mlx5_ib_rq *rq, int new_state,
2543b633e08cSHans Petter Selasky const struct mlx5_modify_raw_qp_param *raw_qp_param, struct ib_pd *pd)
25448e6e287fSHans Petter Selasky {
25458e6e287fSHans Petter Selasky void *in;
25468e6e287fSHans Petter Selasky void *rqc;
25478e6e287fSHans Petter Selasky int inlen;
25488e6e287fSHans Petter Selasky int err;
25498e6e287fSHans Petter Selasky
25508e6e287fSHans Petter Selasky inlen = MLX5_ST_SZ_BYTES(modify_rq_in);
25518e6e287fSHans Petter Selasky in = mlx5_vzalloc(inlen);
25528e6e287fSHans Petter Selasky if (!in)
25538e6e287fSHans Petter Selasky return -ENOMEM;
25548e6e287fSHans Petter Selasky
25558e6e287fSHans Petter Selasky MLX5_SET(modify_rq_in, in, rqn, rq->base.mqp.qpn);
25568e6e287fSHans Petter Selasky MLX5_SET(modify_rq_in, in, rq_state, rq->state);
2557b633e08cSHans Petter Selasky MLX5_SET(modify_rq_in, in, uid, to_mpd(pd)->uid);
25588e6e287fSHans Petter Selasky
25598e6e287fSHans Petter Selasky rqc = MLX5_ADDR_OF(modify_rq_in, in, ctx);
25608e6e287fSHans Petter Selasky MLX5_SET(rqc, rqc, state, new_state);
25618e6e287fSHans Petter Selasky
25628e6e287fSHans Petter Selasky if (raw_qp_param->set_mask & MLX5_RAW_QP_MOD_SET_RQ_Q_CTR_ID) {
25638e6e287fSHans Petter Selasky if (MLX5_CAP_GEN(dev->mdev, modify_rq_counters_set_id)) {
25648e6e287fSHans Petter Selasky MLX5_SET64(modify_rq_in, in, modify_bitmask,
25658e6e287fSHans Petter Selasky MLX5_MODIFY_RQ_IN_MODIFY_BITMASK_MODIFY_RQ_COUNTER_SET_ID);
25668e6e287fSHans Petter Selasky MLX5_SET(rqc, rqc, counter_set_id, raw_qp_param->rq_q_ctr_id);
25678e6e287fSHans Petter Selasky } else
25688e6e287fSHans Petter Selasky pr_info_once("%s: RAW PACKET QP counters are not supported on current FW\n",
25698e6e287fSHans Petter Selasky dev->ib_dev.name);
25708e6e287fSHans Petter Selasky }
25718e6e287fSHans Petter Selasky
25728e6e287fSHans Petter Selasky err = mlx5_core_modify_rq(dev->mdev, in, inlen);
25738e6e287fSHans Petter Selasky if (err)
25748e6e287fSHans Petter Selasky goto out;
25758e6e287fSHans Petter Selasky
25768e6e287fSHans Petter Selasky rq->state = new_state;
25778e6e287fSHans Petter Selasky
25788e6e287fSHans Petter Selasky out:
25798e6e287fSHans Petter Selasky kvfree(in);
25808e6e287fSHans Petter Selasky return err;
25818e6e287fSHans Petter Selasky }
25828e6e287fSHans Petter Selasky
modify_raw_packet_qp_sq(struct mlx5_core_dev * dev,struct mlx5_ib_sq * sq,int new_state,struct ib_pd * pd)25838e6e287fSHans Petter Selasky static int modify_raw_packet_qp_sq(struct mlx5_core_dev *dev,
2584b633e08cSHans Petter Selasky struct mlx5_ib_sq *sq, int new_state,
2585b633e08cSHans Petter Selasky struct ib_pd *pd)
25868e6e287fSHans Petter Selasky {
25878e6e287fSHans Petter Selasky void *in;
25888e6e287fSHans Petter Selasky void *sqc;
25898e6e287fSHans Petter Selasky int inlen;
25908e6e287fSHans Petter Selasky int err;
25918e6e287fSHans Petter Selasky
25928e6e287fSHans Petter Selasky inlen = MLX5_ST_SZ_BYTES(modify_sq_in);
25938e6e287fSHans Petter Selasky in = mlx5_vzalloc(inlen);
25948e6e287fSHans Petter Selasky if (!in)
25958e6e287fSHans Petter Selasky return -ENOMEM;
25968e6e287fSHans Petter Selasky
25978e6e287fSHans Petter Selasky MLX5_SET(modify_sq_in, in, sqn, sq->base.mqp.qpn);
2598b633e08cSHans Petter Selasky MLX5_SET(modify_sq_in, in, uid, to_mpd(pd)->uid);
25998e6e287fSHans Petter Selasky MLX5_SET(modify_sq_in, in, sq_state, sq->state);
26008e6e287fSHans Petter Selasky
26018e6e287fSHans Petter Selasky sqc = MLX5_ADDR_OF(modify_sq_in, in, ctx);
26028e6e287fSHans Petter Selasky MLX5_SET(sqc, sqc, state, new_state);
26038e6e287fSHans Petter Selasky
26048e6e287fSHans Petter Selasky err = mlx5_core_modify_sq(dev, in, inlen);
26058e6e287fSHans Petter Selasky if (err)
26068e6e287fSHans Petter Selasky goto out;
26078e6e287fSHans Petter Selasky
26088e6e287fSHans Petter Selasky sq->state = new_state;
26098e6e287fSHans Petter Selasky
26108e6e287fSHans Petter Selasky out:
26118e6e287fSHans Petter Selasky kvfree(in);
26128e6e287fSHans Petter Selasky return err;
26138e6e287fSHans Petter Selasky }
26148e6e287fSHans Petter Selasky
modify_raw_packet_qp(struct mlx5_ib_dev * dev,struct mlx5_ib_qp * qp,const struct mlx5_modify_raw_qp_param * raw_qp_param,u8 tx_affinity)26158e6e287fSHans Petter Selasky static int modify_raw_packet_qp(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
26168e6e287fSHans Petter Selasky const struct mlx5_modify_raw_qp_param *raw_qp_param,
26178e6e287fSHans Petter Selasky u8 tx_affinity)
26188e6e287fSHans Petter Selasky {
26198e6e287fSHans Petter Selasky struct mlx5_ib_raw_packet_qp *raw_packet_qp = &qp->raw_packet_qp;
26208e6e287fSHans Petter Selasky struct mlx5_ib_rq *rq = &raw_packet_qp->rq;
26218e6e287fSHans Petter Selasky struct mlx5_ib_sq *sq = &raw_packet_qp->sq;
2622b633e08cSHans Petter Selasky int modify_rq = !!qp->rq.wqe_cnt;
2623b633e08cSHans Petter Selasky int modify_sq = !!qp->sq.wqe_cnt;
26248e6e287fSHans Petter Selasky int rq_state;
26258e6e287fSHans Petter Selasky int sq_state;
26268e6e287fSHans Petter Selasky int err;
26278e6e287fSHans Petter Selasky
26288e6e287fSHans Petter Selasky switch (raw_qp_param->operation) {
26298e6e287fSHans Petter Selasky case MLX5_CMD_OP_RST2INIT_QP:
26308e6e287fSHans Petter Selasky rq_state = MLX5_RQC_STATE_RDY;
26318e6e287fSHans Petter Selasky sq_state = MLX5_SQC_STATE_RDY;
26328e6e287fSHans Petter Selasky break;
26338e6e287fSHans Petter Selasky case MLX5_CMD_OP_2ERR_QP:
26348e6e287fSHans Petter Selasky rq_state = MLX5_RQC_STATE_ERR;
26358e6e287fSHans Petter Selasky sq_state = MLX5_SQC_STATE_ERR;
26368e6e287fSHans Petter Selasky break;
26378e6e287fSHans Petter Selasky case MLX5_CMD_OP_2RST_QP:
26388e6e287fSHans Petter Selasky rq_state = MLX5_RQC_STATE_RST;
26398e6e287fSHans Petter Selasky sq_state = MLX5_SQC_STATE_RST;
26408e6e287fSHans Petter Selasky break;
26418e6e287fSHans Petter Selasky case MLX5_CMD_OP_RTR2RTS_QP:
26428e6e287fSHans Petter Selasky case MLX5_CMD_OP_RTS2RTS_QP:
2643b633e08cSHans Petter Selasky return raw_qp_param->set_mask ? -EINVAL : 0;
2644b633e08cSHans Petter Selasky case MLX5_CMD_OP_INIT2INIT_QP:
2645b633e08cSHans Petter Selasky case MLX5_CMD_OP_INIT2RTR_QP:
26468e6e287fSHans Petter Selasky if (raw_qp_param->set_mask)
26478e6e287fSHans Petter Selasky return -EINVAL;
26488e6e287fSHans Petter Selasky else
26498e6e287fSHans Petter Selasky return 0;
26508e6e287fSHans Petter Selasky default:
26518e6e287fSHans Petter Selasky WARN_ON(1);
26528e6e287fSHans Petter Selasky return -EINVAL;
26538e6e287fSHans Petter Selasky }
26548e6e287fSHans Petter Selasky
2655b633e08cSHans Petter Selasky if (modify_rq) {
2656b633e08cSHans Petter Selasky err = modify_raw_packet_qp_rq(dev, rq, rq_state, raw_qp_param,
2657b633e08cSHans Petter Selasky qp->ibqp.pd);
26588e6e287fSHans Petter Selasky if (err)
26598e6e287fSHans Petter Selasky return err;
26608e6e287fSHans Petter Selasky }
26618e6e287fSHans Petter Selasky
2662b633e08cSHans Petter Selasky if (modify_sq) {
26638e6e287fSHans Petter Selasky if (tx_affinity) {
26648e6e287fSHans Petter Selasky err = modify_raw_packet_tx_affinity(dev->mdev, sq,
2665b633e08cSHans Petter Selasky tx_affinity,
2666b633e08cSHans Petter Selasky qp->ibqp.pd);
26678e6e287fSHans Petter Selasky if (err)
26688e6e287fSHans Petter Selasky return err;
26698e6e287fSHans Petter Selasky }
26708e6e287fSHans Petter Selasky
2671b633e08cSHans Petter Selasky return modify_raw_packet_qp_sq(dev->mdev, sq, sq_state, qp->ibqp.pd);
26728e6e287fSHans Petter Selasky }
26738e6e287fSHans Petter Selasky
26748e6e287fSHans Petter Selasky return 0;
26758e6e287fSHans Petter Selasky }
26768e6e287fSHans Petter Selasky
__mlx5_ib_modify_qp(struct ib_qp * ibqp,const struct ib_qp_attr * attr,int attr_mask,enum ib_qp_state cur_state,enum ib_qp_state new_state)267712515907SHans Petter Selasky static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
267812515907SHans Petter Selasky const struct ib_qp_attr *attr, int attr_mask,
267912515907SHans Petter Selasky enum ib_qp_state cur_state, enum ib_qp_state new_state)
268012515907SHans Petter Selasky {
268112515907SHans Petter Selasky static const u16 optab[MLX5_QP_NUM_STATE][MLX5_QP_NUM_STATE] = {
268212515907SHans Petter Selasky [MLX5_QP_STATE_RST] = {
268312515907SHans Petter Selasky [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP,
268412515907SHans Petter Selasky [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP,
268512515907SHans Petter Selasky [MLX5_QP_STATE_INIT] = MLX5_CMD_OP_RST2INIT_QP,
268612515907SHans Petter Selasky },
268712515907SHans Petter Selasky [MLX5_QP_STATE_INIT] = {
268812515907SHans Petter Selasky [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP,
268912515907SHans Petter Selasky [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP,
269012515907SHans Petter Selasky [MLX5_QP_STATE_INIT] = MLX5_CMD_OP_INIT2INIT_QP,
269112515907SHans Petter Selasky [MLX5_QP_STATE_RTR] = MLX5_CMD_OP_INIT2RTR_QP,
269212515907SHans Petter Selasky },
269312515907SHans Petter Selasky [MLX5_QP_STATE_RTR] = {
269412515907SHans Petter Selasky [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP,
269512515907SHans Petter Selasky [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP,
269612515907SHans Petter Selasky [MLX5_QP_STATE_RTS] = MLX5_CMD_OP_RTR2RTS_QP,
269712515907SHans Petter Selasky },
269812515907SHans Petter Selasky [MLX5_QP_STATE_RTS] = {
269912515907SHans Petter Selasky [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP,
270012515907SHans Petter Selasky [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP,
270112515907SHans Petter Selasky [MLX5_QP_STATE_RTS] = MLX5_CMD_OP_RTS2RTS_QP,
270212515907SHans Petter Selasky },
270312515907SHans Petter Selasky [MLX5_QP_STATE_SQD] = {
270412515907SHans Petter Selasky [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP,
270512515907SHans Petter Selasky [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP,
270612515907SHans Petter Selasky },
270712515907SHans Petter Selasky [MLX5_QP_STATE_SQER] = {
270812515907SHans Petter Selasky [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP,
270912515907SHans Petter Selasky [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP,
271012515907SHans Petter Selasky [MLX5_QP_STATE_RTS] = MLX5_CMD_OP_SQERR2RTS_QP,
271112515907SHans Petter Selasky },
271212515907SHans Petter Selasky [MLX5_QP_STATE_ERR] = {
271312515907SHans Petter Selasky [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP,
271412515907SHans Petter Selasky [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP,
271512515907SHans Petter Selasky }
271612515907SHans Petter Selasky };
271712515907SHans Petter Selasky
271812515907SHans Petter Selasky struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
271912515907SHans Petter Selasky struct mlx5_ib_qp *qp = to_mqp(ibqp);
27208e6e287fSHans Petter Selasky struct mlx5_ib_qp_base *base = &qp->trans_qp.base;
272112515907SHans Petter Selasky struct mlx5_ib_cq *send_cq, *recv_cq;
272212515907SHans Petter Selasky struct mlx5_qp_context *context;
272312515907SHans Petter Selasky struct mlx5_ib_pd *pd;
27248e6e287fSHans Petter Selasky struct mlx5_ib_port *mibport = NULL;
272512515907SHans Petter Selasky enum mlx5_qp_state mlx5_cur, mlx5_new;
272612515907SHans Petter Selasky enum mlx5_qp_optpar optpar;
272712515907SHans Petter Selasky int mlx5_st;
272812515907SHans Petter Selasky int err;
272912515907SHans Petter Selasky u16 op;
273012515907SHans Petter Selasky
2731788333d9SHans Petter Selasky context = kzalloc(sizeof(*context), GFP_KERNEL);
2732788333d9SHans Petter Selasky if (!context)
273312515907SHans Petter Selasky return -ENOMEM;
273412515907SHans Petter Selasky
273512515907SHans Petter Selasky err = to_mlx5_st(ibqp->qp_type);
27368e6e287fSHans Petter Selasky if (err < 0) {
27378e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "unsupported qp type %d\n", ibqp->qp_type);
273812515907SHans Petter Selasky goto out;
27398e6e287fSHans Petter Selasky }
274012515907SHans Petter Selasky
274112515907SHans Petter Selasky context->flags = cpu_to_be32(err << 16);
274212515907SHans Petter Selasky
274312515907SHans Petter Selasky if (!(attr_mask & IB_QP_PATH_MIG_STATE)) {
274412515907SHans Petter Selasky context->flags |= cpu_to_be32(MLX5_QP_PM_MIGRATED << 11);
274512515907SHans Petter Selasky } else {
274612515907SHans Petter Selasky switch (attr->path_mig_state) {
274712515907SHans Petter Selasky case IB_MIG_MIGRATED:
274812515907SHans Petter Selasky context->flags |= cpu_to_be32(MLX5_QP_PM_MIGRATED << 11);
274912515907SHans Petter Selasky break;
275012515907SHans Petter Selasky case IB_MIG_REARM:
275112515907SHans Petter Selasky context->flags |= cpu_to_be32(MLX5_QP_PM_REARM << 11);
275212515907SHans Petter Selasky break;
275312515907SHans Petter Selasky case IB_MIG_ARMED:
275412515907SHans Petter Selasky context->flags |= cpu_to_be32(MLX5_QP_PM_ARMED << 11);
275512515907SHans Petter Selasky break;
275612515907SHans Petter Selasky }
275712515907SHans Petter Selasky }
275812515907SHans Petter Selasky
27598e6e287fSHans Petter Selasky if (is_sqp(ibqp->qp_type)) {
276012515907SHans Petter Selasky context->mtu_msgmax = (IB_MTU_256 << 5) | 8;
27618e6e287fSHans Petter Selasky } else if (ibqp->qp_type == IB_QPT_UD ||
27628e6e287fSHans Petter Selasky ibqp->qp_type == MLX5_IB_QPT_REG_UMR) {
276312515907SHans Petter Selasky context->mtu_msgmax = (IB_MTU_4096 << 5) | 12;
276412515907SHans Petter Selasky } else if (attr_mask & IB_QP_PATH_MTU) {
276512515907SHans Petter Selasky if (attr->path_mtu < IB_MTU_256 ||
276612515907SHans Petter Selasky attr->path_mtu > IB_MTU_4096) {
276712515907SHans Petter Selasky mlx5_ib_warn(dev, "invalid mtu %d\n", attr->path_mtu);
276812515907SHans Petter Selasky err = -EINVAL;
276912515907SHans Petter Selasky goto out;
277012515907SHans Petter Selasky }
277112515907SHans Petter Selasky context->mtu_msgmax = (attr->path_mtu << 5) |
277212515907SHans Petter Selasky (u8)MLX5_CAP_GEN(dev->mdev, log_max_msg);
277312515907SHans Petter Selasky }
277412515907SHans Petter Selasky
277512515907SHans Petter Selasky if (attr_mask & IB_QP_DEST_QPN)
277612515907SHans Petter Selasky context->log_pg_sz_remote_qpn = cpu_to_be32(attr->dest_qp_num);
277712515907SHans Petter Selasky
277812515907SHans Petter Selasky if (attr_mask & IB_QP_PKEY_INDEX)
277912515907SHans Petter Selasky context->pri_path.pkey_index = cpu_to_be16(attr->pkey_index);
278012515907SHans Petter Selasky
278112515907SHans Petter Selasky /* todo implement counter_index functionality */
278212515907SHans Petter Selasky
278312515907SHans Petter Selasky if (is_sqp(ibqp->qp_type))
278412515907SHans Petter Selasky context->pri_path.port = qp->port;
278512515907SHans Petter Selasky
278612515907SHans Petter Selasky if (attr_mask & IB_QP_PORT)
278712515907SHans Petter Selasky context->pri_path.port = attr->port_num;
278812515907SHans Petter Selasky
278912515907SHans Petter Selasky if (attr_mask & IB_QP_AV) {
27908e6e287fSHans Petter Selasky err = mlx5_set_path(dev, qp, &attr->ah_attr, &context->pri_path,
279112515907SHans Petter Selasky attr_mask & IB_QP_PORT ? attr->port_num : qp->port,
27928e6e287fSHans Petter Selasky attr_mask, 0, attr, false);
279312515907SHans Petter Selasky if (err)
279412515907SHans Petter Selasky goto out;
279512515907SHans Petter Selasky }
279612515907SHans Petter Selasky
279712515907SHans Petter Selasky if (attr_mask & IB_QP_TIMEOUT)
279812515907SHans Petter Selasky context->pri_path.ackto_lt |= attr->timeout << 3;
279912515907SHans Petter Selasky
280012515907SHans Petter Selasky if (attr_mask & IB_QP_ALT_PATH) {
28018e6e287fSHans Petter Selasky err = mlx5_set_path(dev, qp, &attr->alt_ah_attr,
28028e6e287fSHans Petter Selasky &context->alt_path,
280312515907SHans Petter Selasky attr->alt_port_num,
280412515907SHans Petter Selasky attr_mask | IB_QP_PKEY_INDEX | IB_QP_TIMEOUT,
28058e6e287fSHans Petter Selasky 0, attr, true);
280612515907SHans Petter Selasky if (err)
280712515907SHans Petter Selasky goto out;
280812515907SHans Petter Selasky }
280912515907SHans Petter Selasky
281012515907SHans Petter Selasky pd = get_pd(qp);
281112515907SHans Petter Selasky get_cqs(qp->ibqp.qp_type, qp->ibqp.send_cq, qp->ibqp.recv_cq,
281212515907SHans Petter Selasky &send_cq, &recv_cq);
281312515907SHans Petter Selasky
281412515907SHans Petter Selasky context->flags_pd = cpu_to_be32(pd ? pd->pdn : to_mpd(dev->devr.p0)->pdn);
281512515907SHans Petter Selasky context->cqn_send = send_cq ? cpu_to_be32(send_cq->mcq.cqn) : 0;
281612515907SHans Petter Selasky context->cqn_recv = recv_cq ? cpu_to_be32(recv_cq->mcq.cqn) : 0;
281712515907SHans Petter Selasky context->params1 = cpu_to_be32(MLX5_IB_ACK_REQ_FREQ << 28);
281812515907SHans Petter Selasky
281912515907SHans Petter Selasky if (attr_mask & IB_QP_RNR_RETRY)
282012515907SHans Petter Selasky context->params1 |= cpu_to_be32(attr->rnr_retry << 13);
282112515907SHans Petter Selasky
282212515907SHans Petter Selasky if (attr_mask & IB_QP_RETRY_CNT)
282312515907SHans Petter Selasky context->params1 |= cpu_to_be32(attr->retry_cnt << 16);
282412515907SHans Petter Selasky
282512515907SHans Petter Selasky if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) {
282612515907SHans Petter Selasky if (attr->max_rd_atomic)
282712515907SHans Petter Selasky context->params1 |=
282812515907SHans Petter Selasky cpu_to_be32(fls(attr->max_rd_atomic - 1) << 21);
282912515907SHans Petter Selasky }
283012515907SHans Petter Selasky
283112515907SHans Petter Selasky if (attr_mask & IB_QP_SQ_PSN)
28328e6e287fSHans Petter Selasky context->next_send_psn = cpu_to_be32(attr->sq_psn);
283312515907SHans Petter Selasky
283412515907SHans Petter Selasky if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) {
283512515907SHans Petter Selasky if (attr->max_dest_rd_atomic)
283612515907SHans Petter Selasky context->params2 |=
283712515907SHans Petter Selasky cpu_to_be32(fls(attr->max_dest_rd_atomic - 1) << 21);
283812515907SHans Petter Selasky }
283912515907SHans Petter Selasky
2840cf88b86eSHans Petter Selasky if (attr_mask & (IB_QP_ACCESS_FLAGS | IB_QP_MAX_DEST_RD_ATOMIC)) {
2841cf88b86eSHans Petter Selasky __be32 access_flags;
2842cf88b86eSHans Petter Selasky
2843cf88b86eSHans Petter Selasky err = to_mlx5_access_flags(qp, attr, attr_mask, &access_flags);
2844cf88b86eSHans Petter Selasky if (err)
2845cf88b86eSHans Petter Selasky goto out;
2846cf88b86eSHans Petter Selasky
2847cf88b86eSHans Petter Selasky context->params2 |= access_flags;
2848cf88b86eSHans Petter Selasky }
284912515907SHans Petter Selasky
285012515907SHans Petter Selasky if (attr_mask & IB_QP_MIN_RNR_TIMER)
285112515907SHans Petter Selasky context->rnr_nextrecvpsn |= cpu_to_be32(attr->min_rnr_timer << 24);
285212515907SHans Petter Selasky
285312515907SHans Petter Selasky if (attr_mask & IB_QP_RQ_PSN)
28548e6e287fSHans Petter Selasky context->rnr_nextrecvpsn |= cpu_to_be32(attr->rq_psn);
285512515907SHans Petter Selasky
285612515907SHans Petter Selasky if (attr_mask & IB_QP_QKEY)
285712515907SHans Petter Selasky context->qkey = cpu_to_be32(attr->qkey);
285812515907SHans Petter Selasky
285912515907SHans Petter Selasky if (qp->rq.wqe_cnt && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
286012515907SHans Petter Selasky context->db_rec_addr = cpu_to_be64(qp->db.dma);
286112515907SHans Petter Selasky
286212515907SHans Petter Selasky if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) {
286312515907SHans Petter Selasky u8 port_num = (attr_mask & IB_QP_PORT ? attr->port_num :
286412515907SHans Petter Selasky qp->port) - 1;
28658e6e287fSHans Petter Selasky mibport = &dev->port[port_num];
286612515907SHans Petter Selasky context->qp_counter_set_usr_page |=
28678e6e287fSHans Petter Selasky cpu_to_be32((u32)(mibport->q_cnt_id) << 24);
286812515907SHans Petter Selasky }
286912515907SHans Petter Selasky
28708e6e287fSHans Petter Selasky if (!ibqp->uobject && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
28718e6e287fSHans Petter Selasky context->sq_crq_size |= cpu_to_be16(1 << 4);
28728e6e287fSHans Petter Selasky
28738e6e287fSHans Petter Selasky if (qp->flags & MLX5_IB_QP_SQPN_QP1)
28748e6e287fSHans Petter Selasky context->deth_sqpn = cpu_to_be32(1);
28758e6e287fSHans Petter Selasky
287612515907SHans Petter Selasky mlx5_cur = to_mlx5_state(cur_state);
287712515907SHans Petter Selasky mlx5_new = to_mlx5_state(new_state);
287812515907SHans Petter Selasky mlx5_st = to_mlx5_st(ibqp->qp_type);
287912515907SHans Petter Selasky if (mlx5_st < 0)
288012515907SHans Petter Selasky goto out;
288112515907SHans Petter Selasky
28828e6e287fSHans Petter Selasky /* If moving to a reset or error state, we must disable page faults on
28838e6e287fSHans Petter Selasky * this QP and flush all current page faults. Otherwise a stale page
28848e6e287fSHans Petter Selasky * fault may attempt to work on this QP after it is reset and moved
28858e6e287fSHans Petter Selasky * again to RTS, and may cause the driver and the device to get out of
28868e6e287fSHans Petter Selasky * sync. */
28878e6e287fSHans Petter Selasky if (cur_state != IB_QPS_RESET && cur_state != IB_QPS_ERR &&
28888e6e287fSHans Petter Selasky (new_state == IB_QPS_RESET || new_state == IB_QPS_ERR) &&
28898e6e287fSHans Petter Selasky (qp->ibqp.qp_type != IB_QPT_RAW_PACKET))
28908e6e287fSHans Petter Selasky mlx5_ib_qp_disable_pagefaults(qp);
28918e6e287fSHans Petter Selasky
289212515907SHans Petter Selasky if (mlx5_cur >= MLX5_QP_NUM_STATE || mlx5_new >= MLX5_QP_NUM_STATE ||
289312515907SHans Petter Selasky !optab[mlx5_cur][mlx5_new])
28948e6e287fSHans Petter Selasky goto out;
289512515907SHans Petter Selasky
289612515907SHans Petter Selasky op = optab[mlx5_cur][mlx5_new];
289712515907SHans Petter Selasky optpar = ib_mask_to_mlx5_opt(attr_mask);
289812515907SHans Petter Selasky optpar &= opt_mask[mlx5_cur][mlx5_new][mlx5_st];
289912515907SHans Petter Selasky
29008e6e287fSHans Petter Selasky if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET) {
29018e6e287fSHans Petter Selasky struct mlx5_modify_raw_qp_param raw_qp_param = {};
29028e6e287fSHans Petter Selasky
29038e6e287fSHans Petter Selasky raw_qp_param.operation = op;
29048e6e287fSHans Petter Selasky if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) {
29058e6e287fSHans Petter Selasky raw_qp_param.rq_q_ctr_id = mibport->q_cnt_id;
29068e6e287fSHans Petter Selasky raw_qp_param.set_mask |= MLX5_RAW_QP_MOD_SET_RQ_Q_CTR_ID;
29078e6e287fSHans Petter Selasky }
29088e6e287fSHans Petter Selasky err = modify_raw_packet_qp(dev, qp, &raw_qp_param, 0);
29098e6e287fSHans Petter Selasky } else {
2910788333d9SHans Petter Selasky err = mlx5_core_qp_modify(dev->mdev, op, optpar, context,
2911788333d9SHans Petter Selasky &base->mqp);
29128e6e287fSHans Petter Selasky }
29138e6e287fSHans Petter Selasky
291412515907SHans Petter Selasky if (err)
291512515907SHans Petter Selasky goto out;
291612515907SHans Petter Selasky
29178e6e287fSHans Petter Selasky if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT &&
29188e6e287fSHans Petter Selasky (qp->ibqp.qp_type != IB_QPT_RAW_PACKET))
29198e6e287fSHans Petter Selasky mlx5_ib_qp_enable_pagefaults(qp);
29208e6e287fSHans Petter Selasky
292112515907SHans Petter Selasky qp->state = new_state;
292212515907SHans Petter Selasky
292312515907SHans Petter Selasky if (attr_mask & IB_QP_ACCESS_FLAGS)
29248e6e287fSHans Petter Selasky qp->trans_qp.atomic_rd_en = attr->qp_access_flags;
292512515907SHans Petter Selasky if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
29268e6e287fSHans Petter Selasky qp->trans_qp.resp_depth = attr->max_dest_rd_atomic;
292712515907SHans Petter Selasky if (attr_mask & IB_QP_PORT)
292812515907SHans Petter Selasky qp->port = attr->port_num;
292912515907SHans Petter Selasky if (attr_mask & IB_QP_ALT_PATH)
29308e6e287fSHans Petter Selasky qp->trans_qp.alt_port = attr->alt_port_num;
293112515907SHans Petter Selasky
293212515907SHans Petter Selasky /*
293312515907SHans Petter Selasky * If we moved a kernel QP to RESET, clean up all old CQ
293412515907SHans Petter Selasky * entries and reinitialize the QP.
293512515907SHans Petter Selasky */
293612515907SHans Petter Selasky if (new_state == IB_QPS_RESET && !ibqp->uobject) {
29378e6e287fSHans Petter Selasky mlx5_ib_cq_clean(recv_cq, base->mqp.qpn,
293812515907SHans Petter Selasky ibqp->srq ? to_msrq(ibqp->srq) : NULL);
293912515907SHans Petter Selasky if (send_cq != recv_cq)
29408e6e287fSHans Petter Selasky mlx5_ib_cq_clean(send_cq, base->mqp.qpn, NULL);
294112515907SHans Petter Selasky
294212515907SHans Petter Selasky qp->rq.head = 0;
294312515907SHans Petter Selasky qp->rq.tail = 0;
294412515907SHans Petter Selasky qp->sq.head = 0;
294512515907SHans Petter Selasky qp->sq.tail = 0;
294612515907SHans Petter Selasky qp->sq.cur_post = 0;
294712515907SHans Petter Selasky qp->sq.last_poll = 0;
294812515907SHans Petter Selasky qp->db.db[MLX5_RCV_DBR] = 0;
294912515907SHans Petter Selasky qp->db.db[MLX5_SND_DBR] = 0;
295012515907SHans Petter Selasky }
295112515907SHans Petter Selasky
295212515907SHans Petter Selasky out:
2953788333d9SHans Petter Selasky kfree(context);
295412515907SHans Petter Selasky return err;
295512515907SHans Petter Selasky }
295612515907SHans Petter Selasky
mlx5_ib_modify_qp(struct ib_qp * ibqp,struct ib_qp_attr * attr,int attr_mask,struct ib_udata * udata)295712515907SHans Petter Selasky int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
295812515907SHans Petter Selasky int attr_mask, struct ib_udata *udata)
295912515907SHans Petter Selasky {
296012515907SHans Petter Selasky struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
296112515907SHans Petter Selasky struct mlx5_ib_qp *qp = to_mqp(ibqp);
29628e6e287fSHans Petter Selasky enum ib_qp_type qp_type;
296312515907SHans Petter Selasky enum ib_qp_state cur_state, new_state;
296412515907SHans Petter Selasky int err = -EINVAL;
296512515907SHans Petter Selasky int port;
296612515907SHans Petter Selasky
29678e6e287fSHans Petter Selasky if (ibqp->rwq_ind_tbl)
29688e6e287fSHans Petter Selasky return -ENOSYS;
29698e6e287fSHans Petter Selasky
29708e6e287fSHans Petter Selasky if (unlikely(ibqp->qp_type == IB_QPT_GSI))
29718e6e287fSHans Petter Selasky return mlx5_ib_gsi_modify_qp(ibqp, attr, attr_mask);
29728e6e287fSHans Petter Selasky
29738e6e287fSHans Petter Selasky qp_type = (unlikely(ibqp->qp_type == MLX5_IB_QPT_HW_GSI)) ?
29748e6e287fSHans Petter Selasky IB_QPT_GSI : ibqp->qp_type;
29758e6e287fSHans Petter Selasky
297612515907SHans Petter Selasky mutex_lock(&qp->mutex);
297712515907SHans Petter Selasky
297812515907SHans Petter Selasky cur_state = attr_mask & IB_QP_CUR_STATE ? attr->cur_qp_state : qp->state;
297912515907SHans Petter Selasky new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;
298012515907SHans Petter Selasky
29818e6e287fSHans Petter Selasky if (qp_type != MLX5_IB_QPT_REG_UMR &&
2982d92a9e56SHans Petter Selasky !ib_modify_qp_is_ok(cur_state, new_state, qp_type, attr_mask)) {
29838e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "invalid QP state transition from %d to %d, qp_type %d, attr_mask 0x%x\n",
29848e6e287fSHans Petter Selasky cur_state, new_state, ibqp->qp_type, attr_mask);
298512515907SHans Petter Selasky goto out;
29868e6e287fSHans Petter Selasky }
298712515907SHans Petter Selasky
298812515907SHans Petter Selasky if ((attr_mask & IB_QP_PORT) &&
298912515907SHans Petter Selasky (attr->port_num == 0 ||
29908e6e287fSHans Petter Selasky attr->port_num > MLX5_CAP_GEN(dev->mdev, num_ports))) {
29918e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "invalid port number %d. number of ports is %d\n",
29928e6e287fSHans Petter Selasky attr->port_num, dev->num_ports);
299312515907SHans Petter Selasky goto out;
29948e6e287fSHans Petter Selasky }
299512515907SHans Petter Selasky
299612515907SHans Petter Selasky if (attr_mask & IB_QP_PKEY_INDEX) {
299712515907SHans Petter Selasky port = attr_mask & IB_QP_PORT ? attr->port_num : qp->port;
299812515907SHans Petter Selasky if (attr->pkey_index >=
29998e6e287fSHans Petter Selasky dev->mdev->port_caps[port - 1].pkey_table_len) {
30008e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "invalid pkey index %d\n",
30018e6e287fSHans Petter Selasky attr->pkey_index);
300212515907SHans Petter Selasky goto out;
300312515907SHans Petter Selasky }
30048e6e287fSHans Petter Selasky }
300512515907SHans Petter Selasky
300612515907SHans Petter Selasky if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
300712515907SHans Petter Selasky attr->max_rd_atomic >
30088e6e287fSHans Petter Selasky (1 << MLX5_CAP_GEN(dev->mdev, log_max_ra_res_qp))) {
30098e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "invalid max_rd_atomic value %d\n",
30108e6e287fSHans Petter Selasky attr->max_rd_atomic);
301112515907SHans Petter Selasky goto out;
30128e6e287fSHans Petter Selasky }
301312515907SHans Petter Selasky
301412515907SHans Petter Selasky if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
301512515907SHans Petter Selasky attr->max_dest_rd_atomic >
30168e6e287fSHans Petter Selasky (1 << MLX5_CAP_GEN(dev->mdev, log_max_ra_req_qp))) {
30178e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "invalid max_dest_rd_atomic value %d\n",
30188e6e287fSHans Petter Selasky attr->max_dest_rd_atomic);
301912515907SHans Petter Selasky goto out;
30208e6e287fSHans Petter Selasky }
302112515907SHans Petter Selasky
302212515907SHans Petter Selasky if (cur_state == new_state && cur_state == IB_QPS_RESET) {
302312515907SHans Petter Selasky err = 0;
302412515907SHans Petter Selasky goto out;
302512515907SHans Petter Selasky }
302612515907SHans Petter Selasky
302712515907SHans Petter Selasky err = __mlx5_ib_modify_qp(ibqp, attr, attr_mask, cur_state, new_state);
302812515907SHans Petter Selasky
302912515907SHans Petter Selasky out:
303012515907SHans Petter Selasky mutex_unlock(&qp->mutex);
303112515907SHans Petter Selasky return err;
303212515907SHans Petter Selasky }
303312515907SHans Petter Selasky
mlx5_wq_overflow(struct mlx5_ib_wq * wq,int nreq,struct ib_cq * ib_cq)303412515907SHans Petter Selasky static int mlx5_wq_overflow(struct mlx5_ib_wq *wq, int nreq, struct ib_cq *ib_cq)
303512515907SHans Petter Selasky {
303612515907SHans Petter Selasky struct mlx5_ib_cq *cq;
303712515907SHans Petter Selasky unsigned cur;
303812515907SHans Petter Selasky
303912515907SHans Petter Selasky cur = wq->head - wq->tail;
304012515907SHans Petter Selasky if (likely(cur + nreq < wq->max_post))
304112515907SHans Petter Selasky return 0;
304212515907SHans Petter Selasky
304312515907SHans Petter Selasky cq = to_mcq(ib_cq);
304412515907SHans Petter Selasky spin_lock(&cq->lock);
304512515907SHans Petter Selasky cur = wq->head - wq->tail;
304612515907SHans Petter Selasky spin_unlock(&cq->lock);
304712515907SHans Petter Selasky
304812515907SHans Petter Selasky return cur + nreq >= wq->max_post;
304912515907SHans Petter Selasky }
305012515907SHans Petter Selasky
set_raddr_seg(struct mlx5_wqe_raddr_seg * rseg,u64 remote_addr,u32 rkey)305112515907SHans Petter Selasky static __always_inline void set_raddr_seg(struct mlx5_wqe_raddr_seg *rseg,
305212515907SHans Petter Selasky u64 remote_addr, u32 rkey)
305312515907SHans Petter Selasky {
305412515907SHans Petter Selasky rseg->raddr = cpu_to_be64(remote_addr);
305512515907SHans Petter Selasky rseg->rkey = cpu_to_be32(rkey);
305612515907SHans Petter Selasky rseg->reserved = 0;
305712515907SHans Petter Selasky }
305812515907SHans Petter Selasky
set_eth_seg(struct mlx5_wqe_eth_seg * eseg,const struct ib_send_wr * wr,void * qend,struct mlx5_ib_qp * qp,int * size)30598e6e287fSHans Petter Selasky static void *set_eth_seg(struct mlx5_wqe_eth_seg *eseg,
3060c3987b8eSHans Petter Selasky const struct ib_send_wr *wr, void *qend,
30618e6e287fSHans Petter Selasky struct mlx5_ib_qp *qp, int *size)
30628e6e287fSHans Petter Selasky {
30638e6e287fSHans Petter Selasky void *seg = eseg;
30648e6e287fSHans Petter Selasky
30658e6e287fSHans Petter Selasky memset(eseg, 0, sizeof(struct mlx5_wqe_eth_seg));
30668e6e287fSHans Petter Selasky
30678e6e287fSHans Petter Selasky if (wr->send_flags & IB_SEND_IP_CSUM)
30688e6e287fSHans Petter Selasky eseg->cs_flags = MLX5_ETH_WQE_L3_CSUM |
30698e6e287fSHans Petter Selasky MLX5_ETH_WQE_L4_CSUM;
30708e6e287fSHans Petter Selasky
30718e6e287fSHans Petter Selasky seg += sizeof(struct mlx5_wqe_eth_seg);
30728e6e287fSHans Petter Selasky *size += sizeof(struct mlx5_wqe_eth_seg) / 16;
30738e6e287fSHans Petter Selasky
30748e6e287fSHans Petter Selasky if (wr->opcode == IB_WR_LSO) {
30758e6e287fSHans Petter Selasky struct ib_ud_wr *ud_wr = container_of(wr, struct ib_ud_wr, wr);
30768e6e287fSHans Petter Selasky int size_of_inl_hdr_start = sizeof(eseg->inline_hdr_start);
30778e6e287fSHans Petter Selasky u64 left, leftlen, copysz;
30788e6e287fSHans Petter Selasky void *pdata = ud_wr->header;
30798e6e287fSHans Petter Selasky
30808e6e287fSHans Petter Selasky left = ud_wr->hlen;
30818e6e287fSHans Petter Selasky eseg->mss = cpu_to_be16(ud_wr->mss);
30828e6e287fSHans Petter Selasky eseg->inline_hdr_sz = cpu_to_be16(left);
30838e6e287fSHans Petter Selasky
30848e6e287fSHans Petter Selasky /*
30858e6e287fSHans Petter Selasky * check if there is space till the end of queue, if yes,
30868e6e287fSHans Petter Selasky * copy all in one shot, otherwise copy till the end of queue,
30878e6e287fSHans Petter Selasky * rollback and than the copy the left
30888e6e287fSHans Petter Selasky */
30898e6e287fSHans Petter Selasky leftlen = qend - (void *)eseg->inline_hdr_start;
30908e6e287fSHans Petter Selasky copysz = min_t(u64, leftlen, left);
30918e6e287fSHans Petter Selasky
30928e6e287fSHans Petter Selasky memcpy(seg - size_of_inl_hdr_start, pdata, copysz);
30938e6e287fSHans Petter Selasky
30948e6e287fSHans Petter Selasky if (likely(copysz > size_of_inl_hdr_start)) {
30958e6e287fSHans Petter Selasky seg += ALIGN(copysz - size_of_inl_hdr_start, 16);
30968e6e287fSHans Petter Selasky *size += ALIGN(copysz - size_of_inl_hdr_start, 16) / 16;
30978e6e287fSHans Petter Selasky }
30988e6e287fSHans Petter Selasky
30998e6e287fSHans Petter Selasky if (unlikely(copysz < left)) { /* the last wqe in the queue */
31008e6e287fSHans Petter Selasky seg = mlx5_get_send_wqe(qp, 0);
31018e6e287fSHans Petter Selasky left -= copysz;
31028e6e287fSHans Petter Selasky pdata += copysz;
31038e6e287fSHans Petter Selasky memcpy(seg, pdata, left);
31048e6e287fSHans Petter Selasky seg += ALIGN(left, 16);
31058e6e287fSHans Petter Selasky *size += ALIGN(left, 16) / 16;
31068e6e287fSHans Petter Selasky }
31078e6e287fSHans Petter Selasky }
31088e6e287fSHans Petter Selasky
31098e6e287fSHans Petter Selasky return seg;
31108e6e287fSHans Petter Selasky }
31118e6e287fSHans Petter Selasky
set_datagram_seg(struct mlx5_wqe_datagram_seg * dseg,const struct ib_send_wr * wr)311212515907SHans Petter Selasky static void set_datagram_seg(struct mlx5_wqe_datagram_seg *dseg,
3113c3987b8eSHans Petter Selasky const struct ib_send_wr *wr)
311412515907SHans Petter Selasky {
31158e6e287fSHans Petter Selasky memcpy(&dseg->av, &to_mah(ud_wr(wr)->ah)->av, sizeof(struct mlx5_av));
31168e6e287fSHans Petter Selasky dseg->av.dqp_dct = cpu_to_be32(ud_wr(wr)->remote_qpn | MLX5_EXTENDED_UD_AV);
31178e6e287fSHans Petter Selasky dseg->av.key.qkey.qkey = cpu_to_be32(ud_wr(wr)->remote_qkey);
311812515907SHans Petter Selasky }
311912515907SHans Petter Selasky
set_data_ptr_seg(struct mlx5_wqe_data_seg * dseg,struct ib_sge * sg)312012515907SHans Petter Selasky static void set_data_ptr_seg(struct mlx5_wqe_data_seg *dseg, struct ib_sge *sg)
312112515907SHans Petter Selasky {
312212515907SHans Petter Selasky dseg->byte_count = cpu_to_be32(sg->length);
312312515907SHans Petter Selasky dseg->lkey = cpu_to_be32(sg->lkey);
312412515907SHans Petter Selasky dseg->addr = cpu_to_be64(sg->addr);
312512515907SHans Petter Selasky }
312612515907SHans Petter Selasky
get_klm_octo(int npages)312712515907SHans Petter Selasky static __be16 get_klm_octo(int npages)
312812515907SHans Petter Selasky {
312912515907SHans Petter Selasky return cpu_to_be16(ALIGN(npages, 8) / 2);
313012515907SHans Petter Selasky }
313112515907SHans Petter Selasky
frwr_mkey_mask(void)313212515907SHans Petter Selasky static __be64 frwr_mkey_mask(void)
313312515907SHans Petter Selasky {
313412515907SHans Petter Selasky u64 result;
313512515907SHans Petter Selasky
313612515907SHans Petter Selasky result = MLX5_MKEY_MASK_LEN |
313712515907SHans Petter Selasky MLX5_MKEY_MASK_PAGE_SIZE |
313812515907SHans Petter Selasky MLX5_MKEY_MASK_START_ADDR |
313912515907SHans Petter Selasky MLX5_MKEY_MASK_EN_RINVAL |
314012515907SHans Petter Selasky MLX5_MKEY_MASK_KEY |
314112515907SHans Petter Selasky MLX5_MKEY_MASK_LR |
314212515907SHans Petter Selasky MLX5_MKEY_MASK_LW |
314312515907SHans Petter Selasky MLX5_MKEY_MASK_RR |
314412515907SHans Petter Selasky MLX5_MKEY_MASK_RW |
314512515907SHans Petter Selasky MLX5_MKEY_MASK_A |
314612515907SHans Petter Selasky MLX5_MKEY_MASK_SMALL_FENCE |
314712515907SHans Petter Selasky MLX5_MKEY_MASK_FREE;
314812515907SHans Petter Selasky
314912515907SHans Petter Selasky return cpu_to_be64(result);
315012515907SHans Petter Selasky }
315112515907SHans Petter Selasky
sig_mkey_mask(void)31528e6e287fSHans Petter Selasky static __be64 sig_mkey_mask(void)
315312515907SHans Petter Selasky {
31548e6e287fSHans Petter Selasky u64 result;
315512515907SHans Petter Selasky
31568e6e287fSHans Petter Selasky result = MLX5_MKEY_MASK_LEN |
31578e6e287fSHans Petter Selasky MLX5_MKEY_MASK_PAGE_SIZE |
31588e6e287fSHans Petter Selasky MLX5_MKEY_MASK_START_ADDR |
31598e6e287fSHans Petter Selasky MLX5_MKEY_MASK_EN_SIGERR |
31608e6e287fSHans Petter Selasky MLX5_MKEY_MASK_EN_RINVAL |
31618e6e287fSHans Petter Selasky MLX5_MKEY_MASK_KEY |
31628e6e287fSHans Petter Selasky MLX5_MKEY_MASK_LR |
31638e6e287fSHans Petter Selasky MLX5_MKEY_MASK_LW |
31648e6e287fSHans Petter Selasky MLX5_MKEY_MASK_RR |
31658e6e287fSHans Petter Selasky MLX5_MKEY_MASK_RW |
31668e6e287fSHans Petter Selasky MLX5_MKEY_MASK_SMALL_FENCE |
31678e6e287fSHans Petter Selasky MLX5_MKEY_MASK_FREE |
31688e6e287fSHans Petter Selasky MLX5_MKEY_MASK_BSF_EN;
31698e6e287fSHans Petter Selasky
31708e6e287fSHans Petter Selasky return cpu_to_be64(result);
317112515907SHans Petter Selasky }
317212515907SHans Petter Selasky
set_reg_umr_seg(struct mlx5_wqe_umr_ctrl_seg * umr,struct mlx5_ib_mr * mr)31738e6e287fSHans Petter Selasky static void set_reg_umr_seg(struct mlx5_wqe_umr_ctrl_seg *umr,
31748e6e287fSHans Petter Selasky struct mlx5_ib_mr *mr)
31758e6e287fSHans Petter Selasky {
31768e6e287fSHans Petter Selasky int ndescs = mr->ndescs;
31778e6e287fSHans Petter Selasky
31788e6e287fSHans Petter Selasky memset(umr, 0, sizeof(*umr));
31798e6e287fSHans Petter Selasky
31808e6e287fSHans Petter Selasky if (mr->access_mode == MLX5_ACCESS_MODE_KLM)
31818e6e287fSHans Petter Selasky /* KLMs take twice the size of MTTs */
31828e6e287fSHans Petter Selasky ndescs *= 2;
31838e6e287fSHans Petter Selasky
31848e6e287fSHans Petter Selasky umr->flags = MLX5_UMR_CHECK_NOT_FREE;
31858e6e287fSHans Petter Selasky umr->klm_octowords = get_klm_octo(ndescs);
318612515907SHans Petter Selasky umr->mkey_mask = frwr_mkey_mask();
318712515907SHans Petter Selasky }
318812515907SHans Petter Selasky
set_linv_umr_seg(struct mlx5_wqe_umr_ctrl_seg * umr)31898e6e287fSHans Petter Selasky static void set_linv_umr_seg(struct mlx5_wqe_umr_ctrl_seg *umr)
31908e6e287fSHans Petter Selasky {
31918e6e287fSHans Petter Selasky memset(umr, 0, sizeof(*umr));
31928e6e287fSHans Petter Selasky umr->mkey_mask = cpu_to_be64(MLX5_MKEY_MASK_FREE);
31938e6e287fSHans Petter Selasky umr->flags = 1 << 7;
31948e6e287fSHans Petter Selasky }
31958e6e287fSHans Petter Selasky
get_umr_reg_mr_mask(void)31968e6e287fSHans Petter Selasky static __be64 get_umr_reg_mr_mask(void)
31978e6e287fSHans Petter Selasky {
31988e6e287fSHans Petter Selasky u64 result;
31998e6e287fSHans Petter Selasky
32008e6e287fSHans Petter Selasky result = MLX5_MKEY_MASK_LEN |
32018e6e287fSHans Petter Selasky MLX5_MKEY_MASK_PAGE_SIZE |
32028e6e287fSHans Petter Selasky MLX5_MKEY_MASK_START_ADDR |
32038e6e287fSHans Petter Selasky MLX5_MKEY_MASK_PD |
32048e6e287fSHans Petter Selasky MLX5_MKEY_MASK_LR |
32058e6e287fSHans Petter Selasky MLX5_MKEY_MASK_LW |
32068e6e287fSHans Petter Selasky MLX5_MKEY_MASK_KEY |
32078e6e287fSHans Petter Selasky MLX5_MKEY_MASK_RR |
32088e6e287fSHans Petter Selasky MLX5_MKEY_MASK_RW |
32098e6e287fSHans Petter Selasky MLX5_MKEY_MASK_A |
32108e6e287fSHans Petter Selasky MLX5_MKEY_MASK_FREE;
32118e6e287fSHans Petter Selasky
32128e6e287fSHans Petter Selasky return cpu_to_be64(result);
32138e6e287fSHans Petter Selasky }
32148e6e287fSHans Petter Selasky
get_umr_unreg_mr_mask(void)32158e6e287fSHans Petter Selasky static __be64 get_umr_unreg_mr_mask(void)
32168e6e287fSHans Petter Selasky {
32178e6e287fSHans Petter Selasky u64 result;
32188e6e287fSHans Petter Selasky
32198e6e287fSHans Petter Selasky result = MLX5_MKEY_MASK_FREE;
32208e6e287fSHans Petter Selasky
32218e6e287fSHans Petter Selasky return cpu_to_be64(result);
32228e6e287fSHans Petter Selasky }
32238e6e287fSHans Petter Selasky
get_umr_update_mtt_mask(void)32248e6e287fSHans Petter Selasky static __be64 get_umr_update_mtt_mask(void)
32258e6e287fSHans Petter Selasky {
32268e6e287fSHans Petter Selasky u64 result;
32278e6e287fSHans Petter Selasky
32288e6e287fSHans Petter Selasky result = MLX5_MKEY_MASK_FREE;
32298e6e287fSHans Petter Selasky
32308e6e287fSHans Petter Selasky return cpu_to_be64(result);
32318e6e287fSHans Petter Selasky }
32328e6e287fSHans Petter Selasky
get_umr_update_translation_mask(void)32338e6e287fSHans Petter Selasky static __be64 get_umr_update_translation_mask(void)
32348e6e287fSHans Petter Selasky {
32358e6e287fSHans Petter Selasky u64 result;
32368e6e287fSHans Petter Selasky
32378e6e287fSHans Petter Selasky result = MLX5_MKEY_MASK_LEN |
32388e6e287fSHans Petter Selasky MLX5_MKEY_MASK_PAGE_SIZE |
32398e6e287fSHans Petter Selasky MLX5_MKEY_MASK_START_ADDR |
32408e6e287fSHans Petter Selasky MLX5_MKEY_MASK_KEY |
32418e6e287fSHans Petter Selasky MLX5_MKEY_MASK_FREE;
32428e6e287fSHans Petter Selasky
32438e6e287fSHans Petter Selasky return cpu_to_be64(result);
32448e6e287fSHans Petter Selasky }
32458e6e287fSHans Petter Selasky
get_umr_update_access_mask(void)32468e6e287fSHans Petter Selasky static __be64 get_umr_update_access_mask(void)
32478e6e287fSHans Petter Selasky {
32488e6e287fSHans Petter Selasky u64 result;
32498e6e287fSHans Petter Selasky
32508e6e287fSHans Petter Selasky result = MLX5_MKEY_MASK_LW |
32518e6e287fSHans Petter Selasky MLX5_MKEY_MASK_RR |
32528e6e287fSHans Petter Selasky MLX5_MKEY_MASK_RW |
32538e6e287fSHans Petter Selasky MLX5_MKEY_MASK_A |
32548e6e287fSHans Petter Selasky MLX5_MKEY_MASK_KEY |
32558e6e287fSHans Petter Selasky MLX5_MKEY_MASK_FREE;
32568e6e287fSHans Petter Selasky
32578e6e287fSHans Petter Selasky return cpu_to_be64(result);
32588e6e287fSHans Petter Selasky }
32598e6e287fSHans Petter Selasky
get_umr_update_pd_mask(void)32608e6e287fSHans Petter Selasky static __be64 get_umr_update_pd_mask(void)
32618e6e287fSHans Petter Selasky {
32628e6e287fSHans Petter Selasky u64 result;
32638e6e287fSHans Petter Selasky
32648e6e287fSHans Petter Selasky result = MLX5_MKEY_MASK_PD |
32658e6e287fSHans Petter Selasky MLX5_MKEY_MASK_KEY |
32668e6e287fSHans Petter Selasky MLX5_MKEY_MASK_FREE;
32678e6e287fSHans Petter Selasky
32688e6e287fSHans Petter Selasky return cpu_to_be64(result);
32698e6e287fSHans Petter Selasky }
32708e6e287fSHans Petter Selasky
set_reg_umr_segment(struct mlx5_wqe_umr_ctrl_seg * umr,const struct ib_send_wr * wr)32718e6e287fSHans Petter Selasky static void set_reg_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr,
3272c3987b8eSHans Petter Selasky const struct ib_send_wr *wr)
32738e6e287fSHans Petter Selasky {
3274c3987b8eSHans Petter Selasky const struct mlx5_umr_wr *umrwr = umr_wr(wr);
32758e6e287fSHans Petter Selasky
32768e6e287fSHans Petter Selasky memset(umr, 0, sizeof(*umr));
32778e6e287fSHans Petter Selasky
32788e6e287fSHans Petter Selasky if (wr->send_flags & MLX5_IB_SEND_UMR_FAIL_IF_FREE)
32798e6e287fSHans Petter Selasky umr->flags = MLX5_UMR_CHECK_FREE; /* fail if free */
32808e6e287fSHans Petter Selasky else
32818e6e287fSHans Petter Selasky umr->flags = MLX5_UMR_CHECK_NOT_FREE; /* fail if not free */
32828e6e287fSHans Petter Selasky
32838e6e287fSHans Petter Selasky if (!(wr->send_flags & MLX5_IB_SEND_UMR_UNREG)) {
32848e6e287fSHans Petter Selasky umr->klm_octowords = get_klm_octo(umrwr->npages);
32858e6e287fSHans Petter Selasky if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_MTT) {
32868e6e287fSHans Petter Selasky umr->mkey_mask = get_umr_update_mtt_mask();
32878e6e287fSHans Petter Selasky umr->bsf_octowords = get_klm_octo(umrwr->target.offset);
32888e6e287fSHans Petter Selasky umr->flags |= MLX5_UMR_TRANSLATION_OFFSET_EN;
32898e6e287fSHans Petter Selasky }
32908e6e287fSHans Petter Selasky if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_TRANSLATION)
32918e6e287fSHans Petter Selasky umr->mkey_mask |= get_umr_update_translation_mask();
32928e6e287fSHans Petter Selasky if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_ACCESS)
32938e6e287fSHans Petter Selasky umr->mkey_mask |= get_umr_update_access_mask();
32948e6e287fSHans Petter Selasky if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_PD)
32958e6e287fSHans Petter Selasky umr->mkey_mask |= get_umr_update_pd_mask();
32968e6e287fSHans Petter Selasky if (!umr->mkey_mask)
32978e6e287fSHans Petter Selasky umr->mkey_mask = get_umr_reg_mr_mask();
32988e6e287fSHans Petter Selasky } else {
32998e6e287fSHans Petter Selasky umr->mkey_mask = get_umr_unreg_mr_mask();
33008e6e287fSHans Petter Selasky }
33018e6e287fSHans Petter Selasky
33028e6e287fSHans Petter Selasky if (!wr->num_sge)
33038e6e287fSHans Petter Selasky umr->flags |= MLX5_UMR_INLINE;
33048e6e287fSHans Petter Selasky }
33058e6e287fSHans Petter Selasky
get_umr_flags(int acc)330612515907SHans Petter Selasky static u8 get_umr_flags(int acc)
330712515907SHans Petter Selasky {
330812515907SHans Petter Selasky return (acc & IB_ACCESS_REMOTE_ATOMIC ? MLX5_PERM_ATOMIC : 0) |
330912515907SHans Petter Selasky (acc & IB_ACCESS_REMOTE_WRITE ? MLX5_PERM_REMOTE_WRITE : 0) |
331012515907SHans Petter Selasky (acc & IB_ACCESS_REMOTE_READ ? MLX5_PERM_REMOTE_READ : 0) |
331112515907SHans Petter Selasky (acc & IB_ACCESS_LOCAL_WRITE ? MLX5_PERM_LOCAL_WRITE : 0) |
331212515907SHans Petter Selasky MLX5_PERM_LOCAL_READ | MLX5_PERM_UMR_EN;
331312515907SHans Petter Selasky }
331412515907SHans Petter Selasky
set_reg_mkey_seg(struct mlx5_mkey_seg * seg,struct mlx5_ib_mr * mr,u32 key,int access)33158e6e287fSHans Petter Selasky static void set_reg_mkey_seg(struct mlx5_mkey_seg *seg,
33168e6e287fSHans Petter Selasky struct mlx5_ib_mr *mr,
33178e6e287fSHans Petter Selasky u32 key, int access)
33188e6e287fSHans Petter Selasky {
33198e6e287fSHans Petter Selasky int ndescs = ALIGN(mr->ndescs, 8) >> 1;
33208e6e287fSHans Petter Selasky
33218e6e287fSHans Petter Selasky memset(seg, 0, sizeof(*seg));
33228e6e287fSHans Petter Selasky
33238e6e287fSHans Petter Selasky if (mr->access_mode == MLX5_ACCESS_MODE_MTT)
33248e6e287fSHans Petter Selasky seg->log2_page_size = ilog2(mr->ibmr.page_size);
33258e6e287fSHans Petter Selasky else if (mr->access_mode == MLX5_ACCESS_MODE_KLM)
33268e6e287fSHans Petter Selasky /* KLMs take twice the size of MTTs */
33278e6e287fSHans Petter Selasky ndescs *= 2;
33288e6e287fSHans Petter Selasky
33298e6e287fSHans Petter Selasky seg->flags = get_umr_flags(access) | mr->access_mode;
33308e6e287fSHans Petter Selasky seg->qpn_mkey7_0 = cpu_to_be32((key & 0xff) | 0xffffff00);
33318e6e287fSHans Petter Selasky seg->flags_pd = cpu_to_be32(MLX5_MKEY_REMOTE_INVAL);
33328e6e287fSHans Petter Selasky seg->start_addr = cpu_to_be64(mr->ibmr.iova);
33338e6e287fSHans Petter Selasky seg->len = cpu_to_be64(mr->ibmr.length);
33348e6e287fSHans Petter Selasky seg->xlt_oct_size = cpu_to_be32(ndescs);
33358e6e287fSHans Petter Selasky }
33368e6e287fSHans Petter Selasky
set_linv_mkey_seg(struct mlx5_mkey_seg * seg)33378e6e287fSHans Petter Selasky static void set_linv_mkey_seg(struct mlx5_mkey_seg *seg)
333812515907SHans Petter Selasky {
333912515907SHans Petter Selasky memset(seg, 0, sizeof(*seg));
33408e6e287fSHans Petter Selasky seg->status = MLX5_MKEY_STATUS_FREE;
33418e6e287fSHans Petter Selasky }
33428e6e287fSHans Petter Selasky
set_reg_mkey_segment(struct mlx5_mkey_seg * seg,const struct ib_send_wr * wr)3343c3987b8eSHans Petter Selasky static void set_reg_mkey_segment(struct mlx5_mkey_seg *seg, const struct ib_send_wr *wr)
33448e6e287fSHans Petter Selasky {
3345c3987b8eSHans Petter Selasky const struct mlx5_umr_wr *umrwr = umr_wr(wr);
33468e6e287fSHans Petter Selasky
33478e6e287fSHans Petter Selasky memset(seg, 0, sizeof(*seg));
33488e6e287fSHans Petter Selasky if (wr->send_flags & MLX5_IB_SEND_UMR_UNREG) {
334912515907SHans Petter Selasky seg->status = MLX5_MKEY_STATUS_FREE;
335012515907SHans Petter Selasky return;
335112515907SHans Petter Selasky }
335212515907SHans Petter Selasky
33538e6e287fSHans Petter Selasky seg->flags = convert_access(umrwr->access_flags);
33548e6e287fSHans Petter Selasky if (!(wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_MTT)) {
33558e6e287fSHans Petter Selasky if (umrwr->pd)
33568e6e287fSHans Petter Selasky seg->flags_pd = cpu_to_be32(to_mpd(umrwr->pd)->pdn);
33578e6e287fSHans Petter Selasky seg->start_addr = cpu_to_be64(umrwr->target.virt_addr);
33588e6e287fSHans Petter Selasky }
33598e6e287fSHans Petter Selasky seg->len = cpu_to_be64(umrwr->length);
33608e6e287fSHans Petter Selasky seg->log2_page_size = umrwr->page_shift;
33618e6e287fSHans Petter Selasky seg->qpn_mkey7_0 = cpu_to_be32(0xffffff00 |
33628e6e287fSHans Petter Selasky mlx5_mkey_variant(umrwr->mkey));
336312515907SHans Petter Selasky }
336412515907SHans Petter Selasky
set_reg_data_seg(struct mlx5_wqe_data_seg * dseg,struct mlx5_ib_mr * mr,struct mlx5_ib_pd * pd)33658e6e287fSHans Petter Selasky static void set_reg_data_seg(struct mlx5_wqe_data_seg *dseg,
33668e6e287fSHans Petter Selasky struct mlx5_ib_mr *mr,
33678e6e287fSHans Petter Selasky struct mlx5_ib_pd *pd)
336812515907SHans Petter Selasky {
33698e6e287fSHans Petter Selasky int bcount = mr->desc_size * mr->ndescs;
337012515907SHans Petter Selasky
33718e6e287fSHans Petter Selasky dseg->addr = cpu_to_be64(mr->desc_map);
33728e6e287fSHans Petter Selasky dseg->byte_count = cpu_to_be32(ALIGN(bcount, 64));
33738e6e287fSHans Petter Selasky dseg->lkey = cpu_to_be32(pd->ibpd.local_dma_lkey);
337412515907SHans Petter Selasky }
337512515907SHans Petter Selasky
send_ieth(const struct ib_send_wr * wr)3376c3987b8eSHans Petter Selasky static __be32 send_ieth(const struct ib_send_wr *wr)
337712515907SHans Petter Selasky {
337812515907SHans Petter Selasky switch (wr->opcode) {
337912515907SHans Petter Selasky case IB_WR_SEND_WITH_IMM:
338012515907SHans Petter Selasky case IB_WR_RDMA_WRITE_WITH_IMM:
338112515907SHans Petter Selasky return wr->ex.imm_data;
338212515907SHans Petter Selasky
338312515907SHans Petter Selasky case IB_WR_SEND_WITH_INV:
338412515907SHans Petter Selasky return cpu_to_be32(wr->ex.invalidate_rkey);
338512515907SHans Petter Selasky
338612515907SHans Petter Selasky default:
338712515907SHans Petter Selasky return 0;
338812515907SHans Petter Selasky }
338912515907SHans Petter Selasky }
339012515907SHans Petter Selasky
calc_sig(void * wqe,int size)339112515907SHans Petter Selasky static u8 calc_sig(void *wqe, int size)
339212515907SHans Petter Selasky {
339312515907SHans Petter Selasky u8 *p = wqe;
339412515907SHans Petter Selasky u8 res = 0;
339512515907SHans Petter Selasky int i;
339612515907SHans Petter Selasky
339712515907SHans Petter Selasky for (i = 0; i < size; i++)
339812515907SHans Petter Selasky res ^= p[i];
339912515907SHans Petter Selasky
340012515907SHans Petter Selasky return ~res;
340112515907SHans Petter Selasky }
340212515907SHans Petter Selasky
wq_sig(void * wqe)34038e6e287fSHans Petter Selasky static u8 wq_sig(void *wqe)
340412515907SHans Petter Selasky {
340512515907SHans Petter Selasky return calc_sig(wqe, (*((u8 *)wqe + 8) & 0x3f) << 4);
340612515907SHans Petter Selasky }
340712515907SHans Petter Selasky
set_data_inl_seg(struct mlx5_ib_qp * qp,const struct ib_send_wr * wr,void * wqe,int * sz)3408c3987b8eSHans Petter Selasky static int set_data_inl_seg(struct mlx5_ib_qp *qp, const struct ib_send_wr *wr,
340912515907SHans Petter Selasky void *wqe, int *sz)
341012515907SHans Petter Selasky {
341112515907SHans Petter Selasky struct mlx5_wqe_inline_seg *seg;
341212515907SHans Petter Selasky void *qend = qp->sq.qend;
341312515907SHans Petter Selasky void *addr;
341412515907SHans Petter Selasky int inl = 0;
341512515907SHans Petter Selasky int copy;
341612515907SHans Petter Selasky int len;
341712515907SHans Petter Selasky int i;
341812515907SHans Petter Selasky
341912515907SHans Petter Selasky seg = wqe;
342012515907SHans Petter Selasky wqe += sizeof(*seg);
342112515907SHans Petter Selasky for (i = 0; i < wr->num_sge; i++) {
34228e6e287fSHans Petter Selasky addr = (void *)(unsigned long)(wr->sg_list[i].addr);
342312515907SHans Petter Selasky len = wr->sg_list[i].length;
342412515907SHans Petter Selasky inl += len;
342512515907SHans Petter Selasky
342612515907SHans Petter Selasky if (unlikely(inl > qp->max_inline_data))
342712515907SHans Petter Selasky return -ENOMEM;
342812515907SHans Petter Selasky
342912515907SHans Petter Selasky if (unlikely(wqe + len > qend)) {
34308e6e287fSHans Petter Selasky copy = qend - wqe;
343112515907SHans Petter Selasky memcpy(wqe, addr, copy);
343212515907SHans Petter Selasky addr += copy;
343312515907SHans Petter Selasky len -= copy;
343412515907SHans Petter Selasky wqe = mlx5_get_send_wqe(qp, 0);
343512515907SHans Petter Selasky }
343612515907SHans Petter Selasky memcpy(wqe, addr, len);
343712515907SHans Petter Selasky wqe += len;
343812515907SHans Petter Selasky }
343912515907SHans Petter Selasky
344012515907SHans Petter Selasky seg->byte_count = cpu_to_be32(inl | MLX5_INLINE_SEG);
344112515907SHans Petter Selasky
344212515907SHans Petter Selasky *sz = ALIGN(inl + sizeof(seg->byte_count), 16) / 16;
344312515907SHans Petter Selasky
344412515907SHans Petter Selasky return 0;
344512515907SHans Petter Selasky }
344612515907SHans Petter Selasky
prot_field_size(enum ib_signature_type type)34478e6e287fSHans Petter Selasky static u16 prot_field_size(enum ib_signature_type type)
344812515907SHans Petter Selasky {
34498e6e287fSHans Petter Selasky switch (type) {
34508e6e287fSHans Petter Selasky case IB_SIG_TYPE_T10_DIF:
34518e6e287fSHans Petter Selasky return MLX5_DIF_SIZE;
34528e6e287fSHans Petter Selasky default:
34538e6e287fSHans Petter Selasky return 0;
34548e6e287fSHans Petter Selasky }
34558e6e287fSHans Petter Selasky }
345612515907SHans Petter Selasky
bs_selector(int block_size)34578e6e287fSHans Petter Selasky static u8 bs_selector(int block_size)
34588e6e287fSHans Petter Selasky {
34598e6e287fSHans Petter Selasky switch (block_size) {
34608e6e287fSHans Petter Selasky case 512: return 0x1;
34618e6e287fSHans Petter Selasky case 520: return 0x2;
34628e6e287fSHans Petter Selasky case 4096: return 0x3;
34638e6e287fSHans Petter Selasky case 4160: return 0x4;
34648e6e287fSHans Petter Selasky case 1073741824: return 0x5;
34658e6e287fSHans Petter Selasky default: return 0;
34668e6e287fSHans Petter Selasky }
34678e6e287fSHans Petter Selasky }
34688e6e287fSHans Petter Selasky
mlx5_fill_inl_bsf(struct ib_sig_domain * domain,struct mlx5_bsf_inl * inl)34698e6e287fSHans Petter Selasky static void mlx5_fill_inl_bsf(struct ib_sig_domain *domain,
34708e6e287fSHans Petter Selasky struct mlx5_bsf_inl *inl)
34718e6e287fSHans Petter Selasky {
34728e6e287fSHans Petter Selasky /* Valid inline section and allow BSF refresh */
34738e6e287fSHans Petter Selasky inl->vld_refresh = cpu_to_be16(MLX5_BSF_INL_VALID |
34748e6e287fSHans Petter Selasky MLX5_BSF_REFRESH_DIF);
34758e6e287fSHans Petter Selasky inl->dif_apptag = cpu_to_be16(domain->sig.dif.app_tag);
34768e6e287fSHans Petter Selasky inl->dif_reftag = cpu_to_be32(domain->sig.dif.ref_tag);
34778e6e287fSHans Petter Selasky /* repeating block */
34788e6e287fSHans Petter Selasky inl->rp_inv_seed = MLX5_BSF_REPEAT_BLOCK;
34798e6e287fSHans Petter Selasky inl->sig_type = domain->sig.dif.bg_type == IB_T10DIF_CRC ?
34808e6e287fSHans Petter Selasky MLX5_DIF_CRC : MLX5_DIF_IPCS;
34818e6e287fSHans Petter Selasky
34828e6e287fSHans Petter Selasky if (domain->sig.dif.ref_remap)
34838e6e287fSHans Petter Selasky inl->dif_inc_ref_guard_check |= MLX5_BSF_INC_REFTAG;
34848e6e287fSHans Petter Selasky
34858e6e287fSHans Petter Selasky if (domain->sig.dif.app_escape) {
34868e6e287fSHans Petter Selasky if (domain->sig.dif.ref_escape)
34878e6e287fSHans Petter Selasky inl->dif_inc_ref_guard_check |= MLX5_BSF_APPREF_ESCAPE;
34888e6e287fSHans Petter Selasky else
34898e6e287fSHans Petter Selasky inl->dif_inc_ref_guard_check |= MLX5_BSF_APPTAG_ESCAPE;
34908e6e287fSHans Petter Selasky }
34918e6e287fSHans Petter Selasky
34928e6e287fSHans Petter Selasky inl->dif_app_bitmask_check =
34938e6e287fSHans Petter Selasky cpu_to_be16(domain->sig.dif.apptag_check_mask);
34948e6e287fSHans Petter Selasky }
34958e6e287fSHans Petter Selasky
mlx5_set_bsf(struct ib_mr * sig_mr,struct ib_sig_attrs * sig_attrs,struct mlx5_bsf * bsf,u32 data_size)34968e6e287fSHans Petter Selasky static int mlx5_set_bsf(struct ib_mr *sig_mr,
34978e6e287fSHans Petter Selasky struct ib_sig_attrs *sig_attrs,
34988e6e287fSHans Petter Selasky struct mlx5_bsf *bsf, u32 data_size)
34998e6e287fSHans Petter Selasky {
35008e6e287fSHans Petter Selasky struct mlx5_core_sig_ctx *msig = to_mmr(sig_mr)->sig;
35018e6e287fSHans Petter Selasky struct mlx5_bsf_basic *basic = &bsf->basic;
35028e6e287fSHans Petter Selasky struct ib_sig_domain *mem = &sig_attrs->mem;
35038e6e287fSHans Petter Selasky struct ib_sig_domain *wire = &sig_attrs->wire;
35048e6e287fSHans Petter Selasky
35058e6e287fSHans Petter Selasky memset(bsf, 0, sizeof(*bsf));
35068e6e287fSHans Petter Selasky
35078e6e287fSHans Petter Selasky /* Basic + Extended + Inline */
35088e6e287fSHans Petter Selasky basic->bsf_size_sbs = 1 << 7;
35098e6e287fSHans Petter Selasky /* Input domain check byte mask */
35108e6e287fSHans Petter Selasky basic->check_byte_mask = sig_attrs->check_mask;
35118e6e287fSHans Petter Selasky basic->raw_data_size = cpu_to_be32(data_size);
35128e6e287fSHans Petter Selasky
35138e6e287fSHans Petter Selasky /* Memory domain */
35148e6e287fSHans Petter Selasky switch (sig_attrs->mem.sig_type) {
35158e6e287fSHans Petter Selasky case IB_SIG_TYPE_NONE:
35168e6e287fSHans Petter Selasky break;
35178e6e287fSHans Petter Selasky case IB_SIG_TYPE_T10_DIF:
35188e6e287fSHans Petter Selasky basic->mem.bs_selector = bs_selector(mem->sig.dif.pi_interval);
35198e6e287fSHans Petter Selasky basic->m_bfs_psv = cpu_to_be32(msig->psv_memory.psv_idx);
35208e6e287fSHans Petter Selasky mlx5_fill_inl_bsf(mem, &bsf->m_inl);
35218e6e287fSHans Petter Selasky break;
35228e6e287fSHans Petter Selasky default:
35238e6e287fSHans Petter Selasky return -EINVAL;
35248e6e287fSHans Petter Selasky }
35258e6e287fSHans Petter Selasky
35268e6e287fSHans Petter Selasky /* Wire domain */
35278e6e287fSHans Petter Selasky switch (sig_attrs->wire.sig_type) {
35288e6e287fSHans Petter Selasky case IB_SIG_TYPE_NONE:
35298e6e287fSHans Petter Selasky break;
35308e6e287fSHans Petter Selasky case IB_SIG_TYPE_T10_DIF:
35318e6e287fSHans Petter Selasky if (mem->sig.dif.pi_interval == wire->sig.dif.pi_interval &&
35328e6e287fSHans Petter Selasky mem->sig_type == wire->sig_type) {
35338e6e287fSHans Petter Selasky /* Same block structure */
35348e6e287fSHans Petter Selasky basic->bsf_size_sbs |= 1 << 4;
35358e6e287fSHans Petter Selasky if (mem->sig.dif.bg_type == wire->sig.dif.bg_type)
35368e6e287fSHans Petter Selasky basic->wire.copy_byte_mask |= MLX5_CPY_GRD_MASK;
35378e6e287fSHans Petter Selasky if (mem->sig.dif.app_tag == wire->sig.dif.app_tag)
35388e6e287fSHans Petter Selasky basic->wire.copy_byte_mask |= MLX5_CPY_APP_MASK;
35398e6e287fSHans Petter Selasky if (mem->sig.dif.ref_tag == wire->sig.dif.ref_tag)
35408e6e287fSHans Petter Selasky basic->wire.copy_byte_mask |= MLX5_CPY_REF_MASK;
35418e6e287fSHans Petter Selasky } else
35428e6e287fSHans Petter Selasky basic->wire.bs_selector = bs_selector(wire->sig.dif.pi_interval);
35438e6e287fSHans Petter Selasky
35448e6e287fSHans Petter Selasky basic->w_bfs_psv = cpu_to_be32(msig->psv_wire.psv_idx);
35458e6e287fSHans Petter Selasky mlx5_fill_inl_bsf(wire, &bsf->w_inl);
35468e6e287fSHans Petter Selasky break;
35478e6e287fSHans Petter Selasky default:
35488e6e287fSHans Petter Selasky return -EINVAL;
35498e6e287fSHans Petter Selasky }
35508e6e287fSHans Petter Selasky
35518e6e287fSHans Petter Selasky return 0;
35528e6e287fSHans Petter Selasky }
35538e6e287fSHans Petter Selasky
set_sig_data_segment(const struct ib_sig_handover_wr * wr,struct mlx5_ib_qp * qp,void ** seg,int * size)3554c3987b8eSHans Petter Selasky static int set_sig_data_segment(const struct ib_sig_handover_wr *wr,
35558e6e287fSHans Petter Selasky struct mlx5_ib_qp *qp, void **seg, int *size)
35568e6e287fSHans Petter Selasky {
35578e6e287fSHans Petter Selasky struct ib_sig_attrs *sig_attrs = wr->sig_attrs;
35588e6e287fSHans Petter Selasky struct ib_mr *sig_mr = wr->sig_mr;
35598e6e287fSHans Petter Selasky struct mlx5_bsf *bsf;
35608e6e287fSHans Petter Selasky u32 data_len = wr->wr.sg_list->length;
35618e6e287fSHans Petter Selasky u32 data_key = wr->wr.sg_list->lkey;
35628e6e287fSHans Petter Selasky u64 data_va = wr->wr.sg_list->addr;
35638e6e287fSHans Petter Selasky int ret;
35648e6e287fSHans Petter Selasky int wqe_size;
35658e6e287fSHans Petter Selasky
35668e6e287fSHans Petter Selasky if (!wr->prot ||
35678e6e287fSHans Petter Selasky (data_key == wr->prot->lkey &&
35688e6e287fSHans Petter Selasky data_va == wr->prot->addr &&
35698e6e287fSHans Petter Selasky data_len == wr->prot->length)) {
35708e6e287fSHans Petter Selasky /**
35718e6e287fSHans Petter Selasky * Source domain doesn't contain signature information
35728e6e287fSHans Petter Selasky * or data and protection are interleaved in memory.
35738e6e287fSHans Petter Selasky * So need construct:
35748e6e287fSHans Petter Selasky * ------------------
35758e6e287fSHans Petter Selasky * | data_klm |
35768e6e287fSHans Petter Selasky * ------------------
35778e6e287fSHans Petter Selasky * | BSF |
35788e6e287fSHans Petter Selasky * ------------------
35798e6e287fSHans Petter Selasky **/
35808e6e287fSHans Petter Selasky struct mlx5_klm *data_klm = *seg;
35818e6e287fSHans Petter Selasky
35828e6e287fSHans Petter Selasky data_klm->bcount = cpu_to_be32(data_len);
35838e6e287fSHans Petter Selasky data_klm->key = cpu_to_be32(data_key);
35848e6e287fSHans Petter Selasky data_klm->va = cpu_to_be64(data_va);
35858e6e287fSHans Petter Selasky wqe_size = ALIGN(sizeof(*data_klm), 64);
35868e6e287fSHans Petter Selasky } else {
35878e6e287fSHans Petter Selasky /**
35888e6e287fSHans Petter Selasky * Source domain contains signature information
35898e6e287fSHans Petter Selasky * So need construct a strided block format:
35908e6e287fSHans Petter Selasky * ---------------------------
35918e6e287fSHans Petter Selasky * | stride_block_ctrl |
35928e6e287fSHans Petter Selasky * ---------------------------
35938e6e287fSHans Petter Selasky * | data_klm |
35948e6e287fSHans Petter Selasky * ---------------------------
35958e6e287fSHans Petter Selasky * | prot_klm |
35968e6e287fSHans Petter Selasky * ---------------------------
35978e6e287fSHans Petter Selasky * | BSF |
35988e6e287fSHans Petter Selasky * ---------------------------
35998e6e287fSHans Petter Selasky **/
36008e6e287fSHans Petter Selasky struct mlx5_stride_block_ctrl_seg *sblock_ctrl;
36018e6e287fSHans Petter Selasky struct mlx5_stride_block_entry *data_sentry;
36028e6e287fSHans Petter Selasky struct mlx5_stride_block_entry *prot_sentry;
36038e6e287fSHans Petter Selasky u32 prot_key = wr->prot->lkey;
36048e6e287fSHans Petter Selasky u64 prot_va = wr->prot->addr;
36058e6e287fSHans Petter Selasky u16 block_size = sig_attrs->mem.sig.dif.pi_interval;
36068e6e287fSHans Petter Selasky int prot_size;
36078e6e287fSHans Petter Selasky
36088e6e287fSHans Petter Selasky sblock_ctrl = *seg;
36098e6e287fSHans Petter Selasky data_sentry = (void *)sblock_ctrl + sizeof(*sblock_ctrl);
36108e6e287fSHans Petter Selasky prot_sentry = (void *)data_sentry + sizeof(*data_sentry);
36118e6e287fSHans Petter Selasky
36128e6e287fSHans Petter Selasky prot_size = prot_field_size(sig_attrs->mem.sig_type);
36138e6e287fSHans Petter Selasky if (!prot_size) {
36148e6e287fSHans Petter Selasky pr_err("Bad block size given: %u\n", block_size);
36158e6e287fSHans Petter Selasky return -EINVAL;
36168e6e287fSHans Petter Selasky }
36178e6e287fSHans Petter Selasky sblock_ctrl->bcount_per_cycle = cpu_to_be32(block_size +
36188e6e287fSHans Petter Selasky prot_size);
36198e6e287fSHans Petter Selasky sblock_ctrl->op = cpu_to_be32(MLX5_STRIDE_BLOCK_OP);
36208e6e287fSHans Petter Selasky sblock_ctrl->repeat_count = cpu_to_be32(data_len / block_size);
36218e6e287fSHans Petter Selasky sblock_ctrl->num_entries = cpu_to_be16(2);
36228e6e287fSHans Petter Selasky
36238e6e287fSHans Petter Selasky data_sentry->bcount = cpu_to_be16(block_size);
36248e6e287fSHans Petter Selasky data_sentry->key = cpu_to_be32(data_key);
36258e6e287fSHans Petter Selasky data_sentry->va = cpu_to_be64(data_va);
36268e6e287fSHans Petter Selasky data_sentry->stride = cpu_to_be16(block_size);
36278e6e287fSHans Petter Selasky
36288e6e287fSHans Petter Selasky prot_sentry->bcount = cpu_to_be16(prot_size);
36298e6e287fSHans Petter Selasky prot_sentry->key = cpu_to_be32(prot_key);
36308e6e287fSHans Petter Selasky prot_sentry->va = cpu_to_be64(prot_va);
36318e6e287fSHans Petter Selasky prot_sentry->stride = cpu_to_be16(prot_size);
36328e6e287fSHans Petter Selasky
36338e6e287fSHans Petter Selasky wqe_size = ALIGN(sizeof(*sblock_ctrl) + sizeof(*data_sentry) +
36348e6e287fSHans Petter Selasky sizeof(*prot_sentry), 64);
36358e6e287fSHans Petter Selasky }
36368e6e287fSHans Petter Selasky
36378e6e287fSHans Petter Selasky *seg += wqe_size;
36388e6e287fSHans Petter Selasky *size += wqe_size / 16;
36398e6e287fSHans Petter Selasky if (unlikely((*seg == qp->sq.qend)))
36408e6e287fSHans Petter Selasky *seg = mlx5_get_send_wqe(qp, 0);
36418e6e287fSHans Petter Selasky
36428e6e287fSHans Petter Selasky bsf = *seg;
36438e6e287fSHans Petter Selasky ret = mlx5_set_bsf(sig_mr, sig_attrs, bsf, data_len);
36448e6e287fSHans Petter Selasky if (ret)
364512515907SHans Petter Selasky return -EINVAL;
364612515907SHans Petter Selasky
36478e6e287fSHans Petter Selasky *seg += sizeof(*bsf);
36488e6e287fSHans Petter Selasky *size += sizeof(*bsf) / 16;
36498e6e287fSHans Petter Selasky if (unlikely((*seg == qp->sq.qend)))
36508e6e287fSHans Petter Selasky *seg = mlx5_get_send_wqe(qp, 0);
36518e6e287fSHans Petter Selasky
36528e6e287fSHans Petter Selasky return 0;
36538e6e287fSHans Petter Selasky }
36548e6e287fSHans Petter Selasky
set_sig_mkey_segment(struct mlx5_mkey_seg * seg,const struct ib_sig_handover_wr * wr,u32 nelements,u32 length,u32 pdn)36558e6e287fSHans Petter Selasky static void set_sig_mkey_segment(struct mlx5_mkey_seg *seg,
3656c3987b8eSHans Petter Selasky const struct ib_sig_handover_wr *wr, u32 nelements,
36578e6e287fSHans Petter Selasky u32 length, u32 pdn)
36588e6e287fSHans Petter Selasky {
36598e6e287fSHans Petter Selasky struct ib_mr *sig_mr = wr->sig_mr;
36608e6e287fSHans Petter Selasky u32 sig_key = sig_mr->rkey;
36618e6e287fSHans Petter Selasky u8 sigerr = to_mmr(sig_mr)->sig->sigerr_count & 1;
36628e6e287fSHans Petter Selasky
36638e6e287fSHans Petter Selasky memset(seg, 0, sizeof(*seg));
36648e6e287fSHans Petter Selasky
36658e6e287fSHans Petter Selasky seg->flags = get_umr_flags(wr->access_flags) |
36668e6e287fSHans Petter Selasky MLX5_ACCESS_MODE_KLM;
36678e6e287fSHans Petter Selasky seg->qpn_mkey7_0 = cpu_to_be32((sig_key & 0xff) | 0xffffff00);
36688e6e287fSHans Petter Selasky seg->flags_pd = cpu_to_be32(MLX5_MKEY_REMOTE_INVAL | sigerr << 26 |
36698e6e287fSHans Petter Selasky MLX5_MKEY_BSF_EN | pdn);
36708e6e287fSHans Petter Selasky seg->len = cpu_to_be64(length);
36718e6e287fSHans Petter Selasky seg->xlt_oct_size = cpu_to_be32(be16_to_cpu(get_klm_octo(nelements)));
36728e6e287fSHans Petter Selasky seg->bsfs_octo_size = cpu_to_be32(MLX5_MKEY_BSF_OCTO_SIZE);
36738e6e287fSHans Petter Selasky }
36748e6e287fSHans Petter Selasky
set_sig_umr_segment(struct mlx5_wqe_umr_ctrl_seg * umr,u32 nelements)36758e6e287fSHans Petter Selasky static void set_sig_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr,
36768e6e287fSHans Petter Selasky u32 nelements)
36778e6e287fSHans Petter Selasky {
36788e6e287fSHans Petter Selasky memset(umr, 0, sizeof(*umr));
36798e6e287fSHans Petter Selasky
36808e6e287fSHans Petter Selasky umr->flags = MLX5_FLAGS_INLINE | MLX5_FLAGS_CHECK_FREE;
36818e6e287fSHans Petter Selasky umr->klm_octowords = get_klm_octo(nelements);
36828e6e287fSHans Petter Selasky umr->bsf_octowords = cpu_to_be16(MLX5_MKEY_BSF_OCTO_SIZE);
36838e6e287fSHans Petter Selasky umr->mkey_mask = sig_mkey_mask();
36848e6e287fSHans Petter Selasky }
36858e6e287fSHans Petter Selasky
36868e6e287fSHans Petter Selasky
set_sig_umr_wr(const struct ib_send_wr * send_wr,struct mlx5_ib_qp * qp,void ** seg,int * size)3687c3987b8eSHans Petter Selasky static int set_sig_umr_wr(const struct ib_send_wr *send_wr, struct mlx5_ib_qp *qp,
36888e6e287fSHans Petter Selasky void **seg, int *size)
36898e6e287fSHans Petter Selasky {
3690c3987b8eSHans Petter Selasky const struct ib_sig_handover_wr *wr = sig_handover_wr(send_wr);
36918e6e287fSHans Petter Selasky struct mlx5_ib_mr *sig_mr = to_mmr(wr->sig_mr);
36928e6e287fSHans Petter Selasky u32 pdn = get_pd(qp)->pdn;
36938e6e287fSHans Petter Selasky u32 klm_oct_size;
36948e6e287fSHans Petter Selasky int region_len, ret;
36958e6e287fSHans Petter Selasky
36968e6e287fSHans Petter Selasky if (unlikely(wr->wr.num_sge != 1) ||
36978e6e287fSHans Petter Selasky unlikely(wr->access_flags & IB_ACCESS_REMOTE_ATOMIC) ||
36988e6e287fSHans Petter Selasky unlikely(!sig_mr->sig) || unlikely(!qp->signature_en) ||
36998e6e287fSHans Petter Selasky unlikely(!sig_mr->sig->sig_status_checked))
37008e6e287fSHans Petter Selasky return -EINVAL;
37018e6e287fSHans Petter Selasky
37028e6e287fSHans Petter Selasky /* length of the protected region, data + protection */
37038e6e287fSHans Petter Selasky region_len = wr->wr.sg_list->length;
37048e6e287fSHans Petter Selasky if (wr->prot &&
37058e6e287fSHans Petter Selasky (wr->prot->lkey != wr->wr.sg_list->lkey ||
37068e6e287fSHans Petter Selasky wr->prot->addr != wr->wr.sg_list->addr ||
37078e6e287fSHans Petter Selasky wr->prot->length != wr->wr.sg_list->length))
37088e6e287fSHans Petter Selasky region_len += wr->prot->length;
37098e6e287fSHans Petter Selasky
37108e6e287fSHans Petter Selasky /**
37118e6e287fSHans Petter Selasky * KLM octoword size - if protection was provided
37128e6e287fSHans Petter Selasky * then we use strided block format (3 octowords),
37138e6e287fSHans Petter Selasky * else we use single KLM (1 octoword)
37148e6e287fSHans Petter Selasky **/
37158e6e287fSHans Petter Selasky klm_oct_size = wr->prot ? 3 : 1;
37168e6e287fSHans Petter Selasky
37178e6e287fSHans Petter Selasky set_sig_umr_segment(*seg, klm_oct_size);
371812515907SHans Petter Selasky *seg += sizeof(struct mlx5_wqe_umr_ctrl_seg);
371912515907SHans Petter Selasky *size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16;
372012515907SHans Petter Selasky if (unlikely((*seg == qp->sq.qend)))
372112515907SHans Petter Selasky *seg = mlx5_get_send_wqe(qp, 0);
37228e6e287fSHans Petter Selasky
37238e6e287fSHans Petter Selasky set_sig_mkey_segment(*seg, wr, klm_oct_size, region_len, pdn);
372412515907SHans Petter Selasky *seg += sizeof(struct mlx5_mkey_seg);
372512515907SHans Petter Selasky *size += sizeof(struct mlx5_mkey_seg) / 16;
372612515907SHans Petter Selasky if (unlikely((*seg == qp->sq.qend)))
372712515907SHans Petter Selasky *seg = mlx5_get_send_wqe(qp, 0);
372812515907SHans Petter Selasky
37298e6e287fSHans Petter Selasky ret = set_sig_data_segment(wr, qp, seg, size);
37308e6e287fSHans Petter Selasky if (ret)
37318e6e287fSHans Petter Selasky return ret;
37328e6e287fSHans Petter Selasky
37338e6e287fSHans Petter Selasky sig_mr->sig->sig_status_checked = false;
37348e6e287fSHans Petter Selasky return 0;
37358e6e287fSHans Petter Selasky }
37368e6e287fSHans Petter Selasky
set_psv_wr(struct ib_sig_domain * domain,u32 psv_idx,void ** seg,int * size)37378e6e287fSHans Petter Selasky static int set_psv_wr(struct ib_sig_domain *domain,
37388e6e287fSHans Petter Selasky u32 psv_idx, void **seg, int *size)
37398e6e287fSHans Petter Selasky {
37408e6e287fSHans Petter Selasky struct mlx5_seg_set_psv *psv_seg = *seg;
37418e6e287fSHans Petter Selasky
37428e6e287fSHans Petter Selasky memset(psv_seg, 0, sizeof(*psv_seg));
37438e6e287fSHans Petter Selasky psv_seg->psv_num = cpu_to_be32(psv_idx);
37448e6e287fSHans Petter Selasky switch (domain->sig_type) {
37458e6e287fSHans Petter Selasky case IB_SIG_TYPE_NONE:
37468e6e287fSHans Petter Selasky break;
37478e6e287fSHans Petter Selasky case IB_SIG_TYPE_T10_DIF:
37488e6e287fSHans Petter Selasky psv_seg->transient_sig = cpu_to_be32(domain->sig.dif.bg << 16 |
37498e6e287fSHans Petter Selasky domain->sig.dif.app_tag);
37508e6e287fSHans Petter Selasky psv_seg->ref_tag = cpu_to_be32(domain->sig.dif.ref_tag);
37518e6e287fSHans Petter Selasky break;
37528e6e287fSHans Petter Selasky default:
37538e6e287fSHans Petter Selasky pr_err("Bad signature type given.\n");
37548e6e287fSHans Petter Selasky return 1;
37558e6e287fSHans Petter Selasky }
37568e6e287fSHans Petter Selasky
37578e6e287fSHans Petter Selasky *seg += sizeof(*psv_seg);
37588e6e287fSHans Petter Selasky *size += sizeof(*psv_seg) / 16;
37598e6e287fSHans Petter Selasky
37608e6e287fSHans Petter Selasky return 0;
37618e6e287fSHans Petter Selasky }
37628e6e287fSHans Petter Selasky
set_reg_wr(struct mlx5_ib_qp * qp,const struct ib_reg_wr * wr,void ** seg,int * size)37638e6e287fSHans Petter Selasky static int set_reg_wr(struct mlx5_ib_qp *qp,
3764c3987b8eSHans Petter Selasky const struct ib_reg_wr *wr,
37658e6e287fSHans Petter Selasky void **seg, int *size)
37668e6e287fSHans Petter Selasky {
37678e6e287fSHans Petter Selasky struct mlx5_ib_mr *mr = to_mmr(wr->mr);
37688e6e287fSHans Petter Selasky struct mlx5_ib_pd *pd = to_mpd(qp->ibqp.pd);
37698e6e287fSHans Petter Selasky
37708e6e287fSHans Petter Selasky if (unlikely(wr->wr.send_flags & IB_SEND_INLINE)) {
37718e6e287fSHans Petter Selasky mlx5_ib_warn(to_mdev(qp->ibqp.device),
37728e6e287fSHans Petter Selasky "Invalid IB_SEND_INLINE send flag\n");
37738e6e287fSHans Petter Selasky return -EINVAL;
37748e6e287fSHans Petter Selasky }
37758e6e287fSHans Petter Selasky
37768e6e287fSHans Petter Selasky set_reg_umr_seg(*seg, mr);
37778e6e287fSHans Petter Selasky *seg += sizeof(struct mlx5_wqe_umr_ctrl_seg);
37788e6e287fSHans Petter Selasky *size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16;
37798e6e287fSHans Petter Selasky if (unlikely((*seg == qp->sq.qend)))
37808e6e287fSHans Petter Selasky *seg = mlx5_get_send_wqe(qp, 0);
37818e6e287fSHans Petter Selasky
37828e6e287fSHans Petter Selasky set_reg_mkey_seg(*seg, mr, wr->key, wr->access);
37838e6e287fSHans Petter Selasky *seg += sizeof(struct mlx5_mkey_seg);
37848e6e287fSHans Petter Selasky *size += sizeof(struct mlx5_mkey_seg) / 16;
37858e6e287fSHans Petter Selasky if (unlikely((*seg == qp->sq.qend)))
37868e6e287fSHans Petter Selasky *seg = mlx5_get_send_wqe(qp, 0);
37878e6e287fSHans Petter Selasky
37888e6e287fSHans Petter Selasky set_reg_data_seg(*seg, mr, pd);
378912515907SHans Petter Selasky *seg += sizeof(struct mlx5_wqe_data_seg);
379012515907SHans Petter Selasky *size += (sizeof(struct mlx5_wqe_data_seg) / 16);
37918e6e287fSHans Petter Selasky
379212515907SHans Petter Selasky return 0;
379312515907SHans Petter Selasky }
379412515907SHans Petter Selasky
set_linv_wr(struct mlx5_ib_qp * qp,void ** seg,int * size)37958e6e287fSHans Petter Selasky static void set_linv_wr(struct mlx5_ib_qp *qp, void **seg, int *size)
37968e6e287fSHans Petter Selasky {
37978e6e287fSHans Petter Selasky set_linv_umr_seg(*seg);
37988e6e287fSHans Petter Selasky *seg += sizeof(struct mlx5_wqe_umr_ctrl_seg);
37998e6e287fSHans Petter Selasky *size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16;
38008e6e287fSHans Petter Selasky if (unlikely((*seg == qp->sq.qend)))
38018e6e287fSHans Petter Selasky *seg = mlx5_get_send_wqe(qp, 0);
38028e6e287fSHans Petter Selasky set_linv_mkey_seg(*seg);
38038e6e287fSHans Petter Selasky *seg += sizeof(struct mlx5_mkey_seg);
38048e6e287fSHans Petter Selasky *size += sizeof(struct mlx5_mkey_seg) / 16;
38058e6e287fSHans Petter Selasky if (unlikely((*seg == qp->sq.qend)))
38068e6e287fSHans Petter Selasky *seg = mlx5_get_send_wqe(qp, 0);
38078e6e287fSHans Petter Selasky }
38088e6e287fSHans Petter Selasky
dump_wqe(struct mlx5_ib_qp * qp,int idx,int size_16)380912515907SHans Petter Selasky static void dump_wqe(struct mlx5_ib_qp *qp, int idx, int size_16)
381012515907SHans Petter Selasky {
381112515907SHans Petter Selasky __be32 *p = NULL;
381212515907SHans Petter Selasky int tidx = idx;
381312515907SHans Petter Selasky int i, j;
381412515907SHans Petter Selasky
381512515907SHans Petter Selasky pr_debug("dump wqe at %p\n", mlx5_get_send_wqe(qp, tidx));
381612515907SHans Petter Selasky for (i = 0, j = 0; i < size_16 * 4; i += 4, j += 4) {
381712515907SHans Petter Selasky if ((i & 0xf) == 0) {
381812515907SHans Petter Selasky void *buf = mlx5_get_send_wqe(qp, tidx);
381912515907SHans Petter Selasky tidx = (tidx + 1) & (qp->sq.wqe_cnt - 1);
382012515907SHans Petter Selasky p = buf;
382112515907SHans Petter Selasky j = 0;
382212515907SHans Petter Selasky }
382312515907SHans Petter Selasky pr_debug("%08x %08x %08x %08x\n", be32_to_cpu(p[j]),
382412515907SHans Petter Selasky be32_to_cpu(p[j + 1]), be32_to_cpu(p[j + 2]),
382512515907SHans Petter Selasky be32_to_cpu(p[j + 3]));
382612515907SHans Petter Selasky }
382712515907SHans Petter Selasky }
382812515907SHans Petter Selasky
get_fence(u8 fence,const struct ib_send_wr * wr)3829c3987b8eSHans Petter Selasky static u8 get_fence(u8 fence, const struct ib_send_wr *wr)
383012515907SHans Petter Selasky {
383112515907SHans Petter Selasky if (unlikely(wr->opcode == IB_WR_LOCAL_INV &&
383212515907SHans Petter Selasky wr->send_flags & IB_SEND_FENCE))
383312515907SHans Petter Selasky return MLX5_FENCE_MODE_STRONG_ORDERING;
383412515907SHans Petter Selasky
383512515907SHans Petter Selasky if (unlikely(fence)) {
383612515907SHans Petter Selasky if (wr->send_flags & IB_SEND_FENCE)
383712515907SHans Petter Selasky return MLX5_FENCE_MODE_SMALL_AND_FENCE;
383812515907SHans Petter Selasky else
383912515907SHans Petter Selasky return fence;
38408e6e287fSHans Petter Selasky } else if (unlikely(wr->send_flags & IB_SEND_FENCE)) {
38418e6e287fSHans Petter Selasky return MLX5_FENCE_MODE_FENCE;
384212515907SHans Petter Selasky }
38438e6e287fSHans Petter Selasky
38448e6e287fSHans Petter Selasky return 0;
384512515907SHans Petter Selasky }
384612515907SHans Petter Selasky
begin_wqe(struct mlx5_ib_qp * qp,void ** seg,struct mlx5_wqe_ctrl_seg ** ctrl,const struct ib_send_wr * wr,unsigned * idx,int * size,int nreq,int send_flags)3847b633e08cSHans Petter Selasky static int begin_wqe(struct mlx5_ib_qp *qp, void **seg,
384812515907SHans Petter Selasky struct mlx5_wqe_ctrl_seg **ctrl,
3849c3987b8eSHans Petter Selasky const struct ib_send_wr *wr, unsigned *idx,
3850b633e08cSHans Petter Selasky int *size, int nreq, int send_flags)
385112515907SHans Petter Selasky {
38528e6e287fSHans Petter Selasky if (unlikely(mlx5_wq_overflow(&qp->sq, nreq, qp->ibqp.send_cq)))
38538e6e287fSHans Petter Selasky return -ENOMEM;
385412515907SHans Petter Selasky
385512515907SHans Petter Selasky *idx = qp->sq.cur_post & (qp->sq.wqe_cnt - 1);
385612515907SHans Petter Selasky *seg = mlx5_get_send_wqe(qp, *idx);
385712515907SHans Petter Selasky *ctrl = *seg;
38588e6e287fSHans Petter Selasky *(uint32_t *)(*seg + 8) = 0;
385912515907SHans Petter Selasky (*ctrl)->imm = send_ieth(wr);
386012515907SHans Petter Selasky (*ctrl)->fm_ce_se = qp->sq_signal_bits |
3861b633e08cSHans Petter Selasky (send_flags & IB_SEND_SIGNALED ?
3862b633e08cSHans Petter Selasky MLX5_WQE_CTRL_CQ_UPDATE : 0) |
3863b633e08cSHans Petter Selasky (send_flags & IB_SEND_SOLICITED ?
3864b633e08cSHans Petter Selasky MLX5_WQE_CTRL_SOLICITED : 0);
386512515907SHans Petter Selasky
386612515907SHans Petter Selasky *seg += sizeof(**ctrl);
386712515907SHans Petter Selasky *size = sizeof(**ctrl) / 16;
386812515907SHans Petter Selasky
38698e6e287fSHans Petter Selasky return 0;
387012515907SHans Petter Selasky }
387112515907SHans Petter Selasky
finish_wqe(struct mlx5_ib_qp * qp,struct mlx5_wqe_ctrl_seg * ctrl,u8 size,unsigned idx,u64 wr_id,int nreq,u8 fence,u8 next_fence,u32 mlx5_opcode)387212515907SHans Petter Selasky static void finish_wqe(struct mlx5_ib_qp *qp,
387312515907SHans Petter Selasky struct mlx5_wqe_ctrl_seg *ctrl,
38748e6e287fSHans Petter Selasky u8 size, unsigned idx, u64 wr_id,
387512515907SHans Petter Selasky int nreq, u8 fence, u8 next_fence,
387612515907SHans Petter Selasky u32 mlx5_opcode)
387712515907SHans Petter Selasky {
387812515907SHans Petter Selasky u8 opmod = 0;
387912515907SHans Petter Selasky
388012515907SHans Petter Selasky ctrl->opmod_idx_opcode = cpu_to_be32(((u32)(qp->sq.cur_post) << 8) |
388112515907SHans Petter Selasky mlx5_opcode | ((u32)opmod << 24));
38828e6e287fSHans Petter Selasky ctrl->qpn_ds = cpu_to_be32(size | (qp->trans_qp.base.mqp.qpn << 8));
388312515907SHans Petter Selasky ctrl->fm_ce_se |= fence;
388412515907SHans Petter Selasky qp->fm_cache = next_fence;
388512515907SHans Petter Selasky if (unlikely(qp->wq_sig))
38868e6e287fSHans Petter Selasky ctrl->signature = wq_sig(ctrl);
388712515907SHans Petter Selasky
38888e6e287fSHans Petter Selasky qp->sq.wrid[idx] = wr_id;
38898e6e287fSHans Petter Selasky qp->sq.w_list[idx].opcode = mlx5_opcode;
38908e6e287fSHans Petter Selasky qp->sq.wqe_head[idx] = qp->sq.head + nreq;
389112515907SHans Petter Selasky qp->sq.cur_post += DIV_ROUND_UP(size * 16, MLX5_SEND_WQE_BB);
38928e6e287fSHans Petter Selasky qp->sq.w_list[idx].next = qp->sq.cur_post;
389312515907SHans Petter Selasky }
389412515907SHans Petter Selasky
38958e6e287fSHans Petter Selasky
mlx5_ib_post_send(struct ib_qp * ibqp,const struct ib_send_wr * wr,const struct ib_send_wr ** bad_wr)3896c3987b8eSHans Petter Selasky int mlx5_ib_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr,
3897c3987b8eSHans Petter Selasky const struct ib_send_wr **bad_wr)
389812515907SHans Petter Selasky {
389912515907SHans Petter Selasky struct mlx5_wqe_ctrl_seg *ctrl = NULL; /* compiler warning */
390012515907SHans Petter Selasky struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
390112515907SHans Petter Selasky struct mlx5_core_dev *mdev = dev->mdev;
39028e6e287fSHans Petter Selasky struct mlx5_ib_qp *qp;
39038e6e287fSHans Petter Selasky struct mlx5_ib_mr *mr;
390412515907SHans Petter Selasky struct mlx5_wqe_data_seg *dpseg;
390512515907SHans Petter Selasky struct mlx5_wqe_xrc_seg *xrc;
39068e6e287fSHans Petter Selasky struct mlx5_bf *bf;
390712515907SHans Petter Selasky int uninitialized_var(size);
39088e6e287fSHans Petter Selasky void *qend;
390912515907SHans Petter Selasky unsigned long flags;
391012515907SHans Petter Selasky unsigned idx;
391112515907SHans Petter Selasky int err = 0;
391212515907SHans Petter Selasky int num_sge;
391312515907SHans Petter Selasky void *seg;
391412515907SHans Petter Selasky int nreq;
391512515907SHans Petter Selasky int i;
391612515907SHans Petter Selasky u8 next_fence = 0;
391712515907SHans Petter Selasky u8 fence;
391812515907SHans Petter Selasky
39198e6e287fSHans Petter Selasky if (unlikely(ibqp->qp_type == IB_QPT_GSI))
39208e6e287fSHans Petter Selasky return mlx5_ib_gsi_post_send(ibqp, wr, bad_wr);
39218e6e287fSHans Petter Selasky
39228e6e287fSHans Petter Selasky qp = to_mqp(ibqp);
3923f8f5b459SHans Petter Selasky bf = &qp->bf;
39248e6e287fSHans Petter Selasky qend = qp->sq.qend;
392512515907SHans Petter Selasky
392612515907SHans Petter Selasky spin_lock_irqsave(&qp->sq.lock, flags);
392712515907SHans Petter Selasky
392812515907SHans Petter Selasky if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
392912515907SHans Petter Selasky err = -EIO;
393012515907SHans Petter Selasky *bad_wr = wr;
393112515907SHans Petter Selasky nreq = 0;
393212515907SHans Petter Selasky goto out;
393312515907SHans Petter Selasky }
393412515907SHans Petter Selasky
393512515907SHans Petter Selasky for (nreq = 0; wr; nreq++, wr = wr->next) {
3936dd00abf2SHans Petter Selasky if (unlikely(wr->opcode < 0 || wr->opcode >= ARRAY_SIZE(mlx5_ib_opcode))) {
39378e6e287fSHans Petter Selasky mlx5_ib_warn(dev, "\n");
393812515907SHans Petter Selasky err = -EINVAL;
393912515907SHans Petter Selasky *bad_wr = wr;
394012515907SHans Petter Selasky goto out;
394112515907SHans Petter Selasky }
394212515907SHans Petter Selasky
394312515907SHans Petter Selasky fence = qp->fm_cache;
394412515907SHans Petter Selasky num_sge = wr->num_sge;
394512515907SHans Petter Selasky if (unlikely(num_sge > qp->sq.max_gs)) {
39468e6e287fSHans Petter Selasky mlx5_ib_warn(dev, "\n");
39478e6e287fSHans Petter Selasky err = -EINVAL;
394812515907SHans Petter Selasky *bad_wr = wr;
394912515907SHans Petter Selasky goto out;
395012515907SHans Petter Selasky }
395112515907SHans Petter Selasky
3952b633e08cSHans Petter Selasky err = begin_wqe(qp, &seg, &ctrl, wr, &idx, &size, nreq, wr->send_flags);
395312515907SHans Petter Selasky if (err) {
39548e6e287fSHans Petter Selasky mlx5_ib_warn(dev, "\n");
395512515907SHans Petter Selasky err = -ENOMEM;
395612515907SHans Petter Selasky *bad_wr = wr;
395712515907SHans Petter Selasky goto out;
395812515907SHans Petter Selasky }
395912515907SHans Petter Selasky
396012515907SHans Petter Selasky switch (ibqp->qp_type) {
396112515907SHans Petter Selasky case IB_QPT_XRC_INI:
396212515907SHans Petter Selasky xrc = seg;
396312515907SHans Petter Selasky seg += sizeof(*xrc);
396412515907SHans Petter Selasky size += sizeof(*xrc) / 16;
396512515907SHans Petter Selasky /* fall through */
396612515907SHans Petter Selasky case IB_QPT_RC:
396712515907SHans Petter Selasky switch (wr->opcode) {
396812515907SHans Petter Selasky case IB_WR_RDMA_READ:
396912515907SHans Petter Selasky case IB_WR_RDMA_WRITE:
397012515907SHans Petter Selasky case IB_WR_RDMA_WRITE_WITH_IMM:
39718e6e287fSHans Petter Selasky set_raddr_seg(seg, rdma_wr(wr)->remote_addr,
39728e6e287fSHans Petter Selasky rdma_wr(wr)->rkey);
397312515907SHans Petter Selasky seg += sizeof(struct mlx5_wqe_raddr_seg);
397412515907SHans Petter Selasky size += sizeof(struct mlx5_wqe_raddr_seg) / 16;
397512515907SHans Petter Selasky break;
397612515907SHans Petter Selasky
397712515907SHans Petter Selasky case IB_WR_ATOMIC_CMP_AND_SWP:
397812515907SHans Petter Selasky case IB_WR_ATOMIC_FETCH_AND_ADD:
397912515907SHans Petter Selasky case IB_WR_MASKED_ATOMIC_CMP_AND_SWP:
398012515907SHans Petter Selasky mlx5_ib_warn(dev, "Atomic operations are not supported yet\n");
398112515907SHans Petter Selasky err = -ENOSYS;
398212515907SHans Petter Selasky *bad_wr = wr;
398312515907SHans Petter Selasky goto out;
398412515907SHans Petter Selasky
398512515907SHans Petter Selasky case IB_WR_LOCAL_INV:
398612515907SHans Petter Selasky next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
39878e6e287fSHans Petter Selasky qp->sq.wr_data[idx] = IB_WR_LOCAL_INV;
398812515907SHans Petter Selasky ctrl->imm = cpu_to_be32(wr->ex.invalidate_rkey);
39898e6e287fSHans Petter Selasky set_linv_wr(qp, &seg, &size);
39908e6e287fSHans Petter Selasky num_sge = 0;
39918e6e287fSHans Petter Selasky break;
39928e6e287fSHans Petter Selasky
39938e6e287fSHans Petter Selasky case IB_WR_REG_MR:
39948e6e287fSHans Petter Selasky next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
39958e6e287fSHans Petter Selasky qp->sq.wr_data[idx] = IB_WR_REG_MR;
39968e6e287fSHans Petter Selasky ctrl->imm = cpu_to_be32(reg_wr(wr)->key);
39978e6e287fSHans Petter Selasky err = set_reg_wr(qp, reg_wr(wr), &seg, &size);
399812515907SHans Petter Selasky if (err) {
399912515907SHans Petter Selasky *bad_wr = wr;
400012515907SHans Petter Selasky goto out;
400112515907SHans Petter Selasky }
400212515907SHans Petter Selasky num_sge = 0;
400312515907SHans Petter Selasky break;
400412515907SHans Petter Selasky
40058e6e287fSHans Petter Selasky case IB_WR_REG_SIG_MR:
40068e6e287fSHans Petter Selasky qp->sq.wr_data[idx] = IB_WR_REG_SIG_MR;
40078e6e287fSHans Petter Selasky mr = to_mmr(sig_handover_wr(wr)->sig_mr);
40088e6e287fSHans Petter Selasky
40098e6e287fSHans Petter Selasky ctrl->imm = cpu_to_be32(mr->ibmr.rkey);
40108e6e287fSHans Petter Selasky err = set_sig_umr_wr(wr, qp, &seg, &size);
401112515907SHans Petter Selasky if (err) {
40128e6e287fSHans Petter Selasky mlx5_ib_warn(dev, "\n");
401312515907SHans Petter Selasky *bad_wr = wr;
401412515907SHans Petter Selasky goto out;
401512515907SHans Petter Selasky }
40168e6e287fSHans Petter Selasky
40178e6e287fSHans Petter Selasky finish_wqe(qp, ctrl, size, idx, wr->wr_id,
40188e6e287fSHans Petter Selasky nreq, get_fence(fence, wr),
40198e6e287fSHans Petter Selasky next_fence, MLX5_OPCODE_UMR);
40208e6e287fSHans Petter Selasky /*
40218e6e287fSHans Petter Selasky * SET_PSV WQEs are not signaled and solicited
40228e6e287fSHans Petter Selasky * on error
40238e6e287fSHans Petter Selasky */
4024b633e08cSHans Petter Selasky err = begin_wqe(qp, &seg, &ctrl, wr,
4025b633e08cSHans Petter Selasky &idx, &size, nreq, IB_SEND_SOLICITED);
40268e6e287fSHans Petter Selasky if (err) {
40278e6e287fSHans Petter Selasky mlx5_ib_warn(dev, "\n");
40288e6e287fSHans Petter Selasky err = -ENOMEM;
40298e6e287fSHans Petter Selasky *bad_wr = wr;
40308e6e287fSHans Petter Selasky goto out;
40318e6e287fSHans Petter Selasky }
40328e6e287fSHans Petter Selasky
40338e6e287fSHans Petter Selasky err = set_psv_wr(&sig_handover_wr(wr)->sig_attrs->mem,
40348e6e287fSHans Petter Selasky mr->sig->psv_memory.psv_idx, &seg,
40358e6e287fSHans Petter Selasky &size);
40368e6e287fSHans Petter Selasky if (err) {
40378e6e287fSHans Petter Selasky mlx5_ib_warn(dev, "\n");
40388e6e287fSHans Petter Selasky *bad_wr = wr;
40398e6e287fSHans Petter Selasky goto out;
40408e6e287fSHans Petter Selasky }
40418e6e287fSHans Petter Selasky
40428e6e287fSHans Petter Selasky finish_wqe(qp, ctrl, size, idx, wr->wr_id,
40438e6e287fSHans Petter Selasky nreq, get_fence(fence, wr),
40448e6e287fSHans Petter Selasky next_fence, MLX5_OPCODE_SET_PSV);
4045b633e08cSHans Petter Selasky err = begin_wqe(qp, &seg, &ctrl, wr,
4046b633e08cSHans Petter Selasky &idx, &size, nreq, wr->send_flags);
40478e6e287fSHans Petter Selasky if (err) {
40488e6e287fSHans Petter Selasky mlx5_ib_warn(dev, "\n");
40498e6e287fSHans Petter Selasky err = -ENOMEM;
40508e6e287fSHans Petter Selasky *bad_wr = wr;
40518e6e287fSHans Petter Selasky goto out;
40528e6e287fSHans Petter Selasky }
40538e6e287fSHans Petter Selasky
40548e6e287fSHans Petter Selasky next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
40558e6e287fSHans Petter Selasky err = set_psv_wr(&sig_handover_wr(wr)->sig_attrs->wire,
40568e6e287fSHans Petter Selasky mr->sig->psv_wire.psv_idx, &seg,
40578e6e287fSHans Petter Selasky &size);
40588e6e287fSHans Petter Selasky if (err) {
40598e6e287fSHans Petter Selasky mlx5_ib_warn(dev, "\n");
40608e6e287fSHans Petter Selasky *bad_wr = wr;
40618e6e287fSHans Petter Selasky goto out;
40628e6e287fSHans Petter Selasky }
40638e6e287fSHans Petter Selasky
40648e6e287fSHans Petter Selasky finish_wqe(qp, ctrl, size, idx, wr->wr_id,
40658e6e287fSHans Petter Selasky nreq, get_fence(fence, wr),
40668e6e287fSHans Petter Selasky next_fence, MLX5_OPCODE_SET_PSV);
406712515907SHans Petter Selasky num_sge = 0;
40688e6e287fSHans Petter Selasky goto skip_psv;
406912515907SHans Petter Selasky
407012515907SHans Petter Selasky default:
407112515907SHans Petter Selasky break;
407212515907SHans Petter Selasky }
407312515907SHans Petter Selasky break;
407412515907SHans Petter Selasky
407512515907SHans Petter Selasky case IB_QPT_UC:
407612515907SHans Petter Selasky switch (wr->opcode) {
407712515907SHans Petter Selasky case IB_WR_RDMA_WRITE:
407812515907SHans Petter Selasky case IB_WR_RDMA_WRITE_WITH_IMM:
40798e6e287fSHans Petter Selasky set_raddr_seg(seg, rdma_wr(wr)->remote_addr,
40808e6e287fSHans Petter Selasky rdma_wr(wr)->rkey);
408112515907SHans Petter Selasky seg += sizeof(struct mlx5_wqe_raddr_seg);
408212515907SHans Petter Selasky size += sizeof(struct mlx5_wqe_raddr_seg) / 16;
408312515907SHans Petter Selasky break;
408412515907SHans Petter Selasky
408512515907SHans Petter Selasky default:
408612515907SHans Petter Selasky break;
408712515907SHans Petter Selasky }
408812515907SHans Petter Selasky break;
408912515907SHans Petter Selasky
409012515907SHans Petter Selasky case IB_QPT_SMI:
40918e6e287fSHans Petter Selasky case MLX5_IB_QPT_HW_GSI:
409212515907SHans Petter Selasky set_datagram_seg(seg, wr);
409312515907SHans Petter Selasky seg += sizeof(struct mlx5_wqe_datagram_seg);
409412515907SHans Petter Selasky size += sizeof(struct mlx5_wqe_datagram_seg) / 16;
409512515907SHans Petter Selasky if (unlikely((seg == qend)))
409612515907SHans Petter Selasky seg = mlx5_get_send_wqe(qp, 0);
409712515907SHans Petter Selasky break;
40988e6e287fSHans Petter Selasky case IB_QPT_UD:
40998e6e287fSHans Petter Selasky set_datagram_seg(seg, wr);
41008e6e287fSHans Petter Selasky seg += sizeof(struct mlx5_wqe_datagram_seg);
41018e6e287fSHans Petter Selasky size += sizeof(struct mlx5_wqe_datagram_seg) / 16;
41028e6e287fSHans Petter Selasky
41038e6e287fSHans Petter Selasky if (unlikely((seg == qend)))
41048e6e287fSHans Petter Selasky seg = mlx5_get_send_wqe(qp, 0);
41058e6e287fSHans Petter Selasky
41068e6e287fSHans Petter Selasky /* handle qp that supports ud offload */
41078e6e287fSHans Petter Selasky if (qp->flags & IB_QP_CREATE_IPOIB_UD_LSO) {
41088e6e287fSHans Petter Selasky struct mlx5_wqe_eth_pad *pad;
41098e6e287fSHans Petter Selasky
41108e6e287fSHans Petter Selasky pad = seg;
41118e6e287fSHans Petter Selasky memset(pad, 0, sizeof(struct mlx5_wqe_eth_pad));
41128e6e287fSHans Petter Selasky seg += sizeof(struct mlx5_wqe_eth_pad);
41138e6e287fSHans Petter Selasky size += sizeof(struct mlx5_wqe_eth_pad) / 16;
41148e6e287fSHans Petter Selasky
41158e6e287fSHans Petter Selasky seg = set_eth_seg(seg, wr, qend, qp, &size);
41168e6e287fSHans Petter Selasky
41178e6e287fSHans Petter Selasky if (unlikely((seg == qend)))
41188e6e287fSHans Petter Selasky seg = mlx5_get_send_wqe(qp, 0);
41198e6e287fSHans Petter Selasky }
41208e6e287fSHans Petter Selasky break;
41218e6e287fSHans Petter Selasky case MLX5_IB_QPT_REG_UMR:
41228e6e287fSHans Petter Selasky if (wr->opcode != MLX5_IB_WR_UMR) {
41238e6e287fSHans Petter Selasky err = -EINVAL;
41248e6e287fSHans Petter Selasky mlx5_ib_warn(dev, "bad opcode\n");
41258e6e287fSHans Petter Selasky goto out;
41268e6e287fSHans Petter Selasky }
41278e6e287fSHans Petter Selasky qp->sq.wr_data[idx] = MLX5_IB_WR_UMR;
41288e6e287fSHans Petter Selasky ctrl->imm = cpu_to_be32(umr_wr(wr)->mkey);
41298e6e287fSHans Petter Selasky set_reg_umr_segment(seg, wr);
41308e6e287fSHans Petter Selasky seg += sizeof(struct mlx5_wqe_umr_ctrl_seg);
41318e6e287fSHans Petter Selasky size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16;
41328e6e287fSHans Petter Selasky if (unlikely((seg == qend)))
41338e6e287fSHans Petter Selasky seg = mlx5_get_send_wqe(qp, 0);
41348e6e287fSHans Petter Selasky set_reg_mkey_segment(seg, wr);
41358e6e287fSHans Petter Selasky seg += sizeof(struct mlx5_mkey_seg);
41368e6e287fSHans Petter Selasky size += sizeof(struct mlx5_mkey_seg) / 16;
41378e6e287fSHans Petter Selasky if (unlikely((seg == qend)))
41388e6e287fSHans Petter Selasky seg = mlx5_get_send_wqe(qp, 0);
41398e6e287fSHans Petter Selasky break;
41408e6e287fSHans Petter Selasky
414112515907SHans Petter Selasky default:
414212515907SHans Petter Selasky break;
414312515907SHans Petter Selasky }
414412515907SHans Petter Selasky
414512515907SHans Petter Selasky if (wr->send_flags & IB_SEND_INLINE && num_sge) {
414612515907SHans Petter Selasky int uninitialized_var(sz);
414712515907SHans Petter Selasky
414812515907SHans Petter Selasky err = set_data_inl_seg(qp, wr, seg, &sz);
414912515907SHans Petter Selasky if (unlikely(err)) {
41508e6e287fSHans Petter Selasky mlx5_ib_warn(dev, "\n");
415112515907SHans Petter Selasky *bad_wr = wr;
415212515907SHans Petter Selasky goto out;
415312515907SHans Petter Selasky }
415412515907SHans Petter Selasky size += sz;
415512515907SHans Petter Selasky } else {
415612515907SHans Petter Selasky dpseg = seg;
415712515907SHans Petter Selasky for (i = 0; i < num_sge; i++) {
415812515907SHans Petter Selasky if (unlikely(dpseg == qend)) {
415912515907SHans Petter Selasky seg = mlx5_get_send_wqe(qp, 0);
416012515907SHans Petter Selasky dpseg = seg;
416112515907SHans Petter Selasky }
416212515907SHans Petter Selasky if (likely(wr->sg_list[i].length)) {
416312515907SHans Petter Selasky set_data_ptr_seg(dpseg, wr->sg_list + i);
416412515907SHans Petter Selasky size += sizeof(struct mlx5_wqe_data_seg) / 16;
416512515907SHans Petter Selasky dpseg++;
416612515907SHans Petter Selasky }
416712515907SHans Petter Selasky }
416812515907SHans Petter Selasky }
416912515907SHans Petter Selasky
41708e6e287fSHans Petter Selasky finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq,
417112515907SHans Petter Selasky get_fence(fence, wr), next_fence,
417212515907SHans Petter Selasky mlx5_ib_opcode[wr->opcode]);
41738e6e287fSHans Petter Selasky skip_psv:
417412515907SHans Petter Selasky if (0)
417512515907SHans Petter Selasky dump_wqe(qp, idx, size);
417612515907SHans Petter Selasky }
417712515907SHans Petter Selasky
417812515907SHans Petter Selasky out:
417912515907SHans Petter Selasky if (likely(nreq)) {
418012515907SHans Petter Selasky qp->sq.head += nreq;
418112515907SHans Petter Selasky
418212515907SHans Petter Selasky /* Make sure that descriptors are written before
418312515907SHans Petter Selasky * updating doorbell record and ringing the doorbell
418412515907SHans Petter Selasky */
418512515907SHans Petter Selasky wmb();
418612515907SHans Petter Selasky
418712515907SHans Petter Selasky qp->db.db[MLX5_SND_DBR] = cpu_to_be32(qp->sq.cur_post);
418812515907SHans Petter Selasky
418912515907SHans Petter Selasky /* Make sure doorbell record is visible to the HCA before
419012515907SHans Petter Selasky * we hit doorbell */
419112515907SHans Petter Selasky wmb();
419212515907SHans Petter Selasky
4193f8f5b459SHans Petter Selasky mlx5_write64((__be32 *)ctrl, bf->bfreg->map + bf->offset,
419412515907SHans Petter Selasky MLX5_GET_DOORBELL_LOCK(&bf->lock32));
419512515907SHans Petter Selasky /* Make sure doorbells don't leak out of SQ spinlock
419612515907SHans Petter Selasky * and reach the HCA out of order.
419712515907SHans Petter Selasky */
419812515907SHans Petter Selasky bf->offset ^= bf->buf_size;
419912515907SHans Petter Selasky }
420012515907SHans Petter Selasky
420112515907SHans Petter Selasky spin_unlock_irqrestore(&qp->sq.lock, flags);
420212515907SHans Petter Selasky
420312515907SHans Petter Selasky return err;
420412515907SHans Petter Selasky }
420512515907SHans Petter Selasky
set_sig_seg(struct mlx5_rwqe_sig * sig,int size)420612515907SHans Petter Selasky static void set_sig_seg(struct mlx5_rwqe_sig *sig, int size)
420712515907SHans Petter Selasky {
420812515907SHans Petter Selasky sig->signature = calc_sig(sig, size);
420912515907SHans Petter Selasky }
421012515907SHans Petter Selasky
mlx5_ib_post_recv(struct ib_qp * ibqp,const struct ib_recv_wr * wr,const struct ib_recv_wr ** bad_wr)4211c3987b8eSHans Petter Selasky int mlx5_ib_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr,
4212c3987b8eSHans Petter Selasky const struct ib_recv_wr **bad_wr)
421312515907SHans Petter Selasky {
421412515907SHans Petter Selasky struct mlx5_ib_qp *qp = to_mqp(ibqp);
421512515907SHans Petter Selasky struct mlx5_wqe_data_seg *scat;
421612515907SHans Petter Selasky struct mlx5_rwqe_sig *sig;
421712515907SHans Petter Selasky struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
421812515907SHans Petter Selasky struct mlx5_core_dev *mdev = dev->mdev;
421912515907SHans Petter Selasky unsigned long flags;
422012515907SHans Petter Selasky int err = 0;
422112515907SHans Petter Selasky int nreq;
422212515907SHans Petter Selasky int ind;
422312515907SHans Petter Selasky int i;
422412515907SHans Petter Selasky
42258e6e287fSHans Petter Selasky if (unlikely(ibqp->qp_type == IB_QPT_GSI))
42268e6e287fSHans Petter Selasky return mlx5_ib_gsi_post_recv(ibqp, wr, bad_wr);
42278e6e287fSHans Petter Selasky
422812515907SHans Petter Selasky spin_lock_irqsave(&qp->rq.lock, flags);
422912515907SHans Petter Selasky
423012515907SHans Petter Selasky if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
423112515907SHans Petter Selasky err = -EIO;
423212515907SHans Petter Selasky *bad_wr = wr;
423312515907SHans Petter Selasky nreq = 0;
423412515907SHans Petter Selasky goto out;
423512515907SHans Petter Selasky }
423612515907SHans Petter Selasky
423712515907SHans Petter Selasky ind = qp->rq.head & (qp->rq.wqe_cnt - 1);
423812515907SHans Petter Selasky
423912515907SHans Petter Selasky for (nreq = 0; wr; nreq++, wr = wr->next) {
424012515907SHans Petter Selasky if (mlx5_wq_overflow(&qp->rq, nreq, qp->ibqp.recv_cq)) {
424112515907SHans Petter Selasky err = -ENOMEM;
424212515907SHans Petter Selasky *bad_wr = wr;
424312515907SHans Petter Selasky goto out;
424412515907SHans Petter Selasky }
424512515907SHans Petter Selasky
424612515907SHans Petter Selasky if (unlikely(wr->num_sge > qp->rq.max_gs)) {
424712515907SHans Petter Selasky err = -EINVAL;
424812515907SHans Petter Selasky *bad_wr = wr;
424912515907SHans Petter Selasky goto out;
425012515907SHans Petter Selasky }
425112515907SHans Petter Selasky
425212515907SHans Petter Selasky scat = get_recv_wqe(qp, ind);
425312515907SHans Petter Selasky if (qp->wq_sig)
425412515907SHans Petter Selasky scat++;
425512515907SHans Petter Selasky
425612515907SHans Petter Selasky for (i = 0; i < wr->num_sge; i++)
425712515907SHans Petter Selasky set_data_ptr_seg(scat + i, wr->sg_list + i);
425812515907SHans Petter Selasky
425912515907SHans Petter Selasky if (i < qp->rq.max_gs) {
426012515907SHans Petter Selasky scat[i].byte_count = 0;
426112515907SHans Petter Selasky scat[i].lkey = cpu_to_be32(MLX5_INVALID_LKEY);
426212515907SHans Petter Selasky scat[i].addr = 0;
426312515907SHans Petter Selasky }
426412515907SHans Petter Selasky
426512515907SHans Petter Selasky if (qp->wq_sig) {
426612515907SHans Petter Selasky sig = (struct mlx5_rwqe_sig *)scat;
426712515907SHans Petter Selasky set_sig_seg(sig, (qp->rq.max_gs + 1) << 2);
426812515907SHans Petter Selasky }
426912515907SHans Petter Selasky
42708e6e287fSHans Petter Selasky qp->rq.wrid[ind] = wr->wr_id;
427112515907SHans Petter Selasky
427212515907SHans Petter Selasky ind = (ind + 1) & (qp->rq.wqe_cnt - 1);
427312515907SHans Petter Selasky }
427412515907SHans Petter Selasky
427512515907SHans Petter Selasky out:
427612515907SHans Petter Selasky if (likely(nreq)) {
427712515907SHans Petter Selasky qp->rq.head += nreq;
427812515907SHans Petter Selasky
427912515907SHans Petter Selasky /* Make sure that descriptors are written before
428012515907SHans Petter Selasky * doorbell record.
428112515907SHans Petter Selasky */
428212515907SHans Petter Selasky wmb();
428312515907SHans Petter Selasky
428412515907SHans Petter Selasky *qp->db.db = cpu_to_be32(qp->rq.head & 0xffff);
428512515907SHans Petter Selasky }
428612515907SHans Petter Selasky
428712515907SHans Petter Selasky spin_unlock_irqrestore(&qp->rq.lock, flags);
428812515907SHans Petter Selasky
428912515907SHans Petter Selasky return err;
429012515907SHans Petter Selasky }
429112515907SHans Petter Selasky
to_ib_qp_state(enum mlx5_qp_state mlx5_state)429212515907SHans Petter Selasky static inline enum ib_qp_state to_ib_qp_state(enum mlx5_qp_state mlx5_state)
429312515907SHans Petter Selasky {
429412515907SHans Petter Selasky switch (mlx5_state) {
429512515907SHans Petter Selasky case MLX5_QP_STATE_RST: return IB_QPS_RESET;
429612515907SHans Petter Selasky case MLX5_QP_STATE_INIT: return IB_QPS_INIT;
429712515907SHans Petter Selasky case MLX5_QP_STATE_RTR: return IB_QPS_RTR;
429812515907SHans Petter Selasky case MLX5_QP_STATE_RTS: return IB_QPS_RTS;
429912515907SHans Petter Selasky case MLX5_QP_STATE_SQ_DRAINING:
430012515907SHans Petter Selasky case MLX5_QP_STATE_SQD: return IB_QPS_SQD;
430112515907SHans Petter Selasky case MLX5_QP_STATE_SQER: return IB_QPS_SQE;
430212515907SHans Petter Selasky case MLX5_QP_STATE_ERR: return IB_QPS_ERR;
430312515907SHans Petter Selasky default: return -1;
430412515907SHans Petter Selasky }
430512515907SHans Petter Selasky }
430612515907SHans Petter Selasky
to_ib_mig_state(int mlx5_mig_state)430712515907SHans Petter Selasky static inline enum ib_mig_state to_ib_mig_state(int mlx5_mig_state)
430812515907SHans Petter Selasky {
430912515907SHans Petter Selasky switch (mlx5_mig_state) {
431012515907SHans Petter Selasky case MLX5_QP_PM_ARMED: return IB_MIG_ARMED;
431112515907SHans Petter Selasky case MLX5_QP_PM_REARM: return IB_MIG_REARM;
431212515907SHans Petter Selasky case MLX5_QP_PM_MIGRATED: return IB_MIG_MIGRATED;
431312515907SHans Petter Selasky default: return -1;
431412515907SHans Petter Selasky }
431512515907SHans Petter Selasky }
431612515907SHans Petter Selasky
to_ib_qp_access_flags(int mlx5_flags)431712515907SHans Petter Selasky static int to_ib_qp_access_flags(int mlx5_flags)
431812515907SHans Petter Selasky {
431912515907SHans Petter Selasky int ib_flags = 0;
432012515907SHans Petter Selasky
432112515907SHans Petter Selasky if (mlx5_flags & MLX5_QP_BIT_RRE)
432212515907SHans Petter Selasky ib_flags |= IB_ACCESS_REMOTE_READ;
432312515907SHans Petter Selasky if (mlx5_flags & MLX5_QP_BIT_RWE)
432412515907SHans Petter Selasky ib_flags |= IB_ACCESS_REMOTE_WRITE;
432512515907SHans Petter Selasky if (mlx5_flags & MLX5_QP_BIT_RAE)
432612515907SHans Petter Selasky ib_flags |= IB_ACCESS_REMOTE_ATOMIC;
432712515907SHans Petter Selasky
432812515907SHans Petter Selasky return ib_flags;
432912515907SHans Petter Selasky }
433012515907SHans Petter Selasky
to_ib_ah_attr(struct mlx5_ib_dev * ibdev,struct ib_ah_attr * ib_ah_attr,struct mlx5_qp_path * path)433112515907SHans Petter Selasky static void to_ib_ah_attr(struct mlx5_ib_dev *ibdev, struct ib_ah_attr *ib_ah_attr,
433212515907SHans Petter Selasky struct mlx5_qp_path *path)
433312515907SHans Petter Selasky {
433412515907SHans Petter Selasky struct mlx5_core_dev *dev = ibdev->mdev;
433512515907SHans Petter Selasky
433612515907SHans Petter Selasky memset(ib_ah_attr, 0, sizeof(*ib_ah_attr));
433712515907SHans Petter Selasky ib_ah_attr->port_num = path->port;
433812515907SHans Petter Selasky
433912515907SHans Petter Selasky if (ib_ah_attr->port_num == 0 ||
434012515907SHans Petter Selasky ib_ah_attr->port_num > MLX5_CAP_GEN(dev, num_ports))
434112515907SHans Petter Selasky return;
434212515907SHans Petter Selasky
434312515907SHans Petter Selasky ib_ah_attr->sl = path->dci_cfi_prio_sl & 0xf;
434412515907SHans Petter Selasky
434512515907SHans Petter Selasky ib_ah_attr->dlid = be16_to_cpu(path->rlid);
434612515907SHans Petter Selasky ib_ah_attr->src_path_bits = path->grh_mlid & 0x7f;
434712515907SHans Petter Selasky ib_ah_attr->static_rate = path->static_rate ? path->static_rate - 5 : 0;
434812515907SHans Petter Selasky ib_ah_attr->ah_flags = (path->grh_mlid & (1 << 7)) ? IB_AH_GRH : 0;
434912515907SHans Petter Selasky if (ib_ah_attr->ah_flags) {
435012515907SHans Petter Selasky ib_ah_attr->grh.sgid_index = path->mgid_index;
435112515907SHans Petter Selasky ib_ah_attr->grh.hop_limit = path->hop_limit;
435212515907SHans Petter Selasky ib_ah_attr->grh.traffic_class =
435312515907SHans Petter Selasky (be32_to_cpu(path->tclass_flowlabel) >> 20) & 0xff;
435412515907SHans Petter Selasky ib_ah_attr->grh.flow_label =
435512515907SHans Petter Selasky be32_to_cpu(path->tclass_flowlabel) & 0xfffff;
435612515907SHans Petter Selasky memcpy(ib_ah_attr->grh.dgid.raw,
435712515907SHans Petter Selasky path->rgid, sizeof(ib_ah_attr->grh.dgid.raw));
435812515907SHans Petter Selasky }
435912515907SHans Petter Selasky }
436012515907SHans Petter Selasky
query_raw_packet_qp_sq_state(struct mlx5_ib_dev * dev,struct mlx5_ib_sq * sq,u8 * sq_state)43618e6e287fSHans Petter Selasky static int query_raw_packet_qp_sq_state(struct mlx5_ib_dev *dev,
43628e6e287fSHans Petter Selasky struct mlx5_ib_sq *sq,
43638e6e287fSHans Petter Selasky u8 *sq_state)
436412515907SHans Petter Selasky {
43658e6e287fSHans Petter Selasky void *out;
43668e6e287fSHans Petter Selasky void *sqc;
43678e6e287fSHans Petter Selasky int inlen;
43688e6e287fSHans Petter Selasky int err;
43698e6e287fSHans Petter Selasky
43708e6e287fSHans Petter Selasky inlen = MLX5_ST_SZ_BYTES(query_sq_out);
43718e6e287fSHans Petter Selasky out = mlx5_vzalloc(inlen);
43728e6e287fSHans Petter Selasky if (!out)
43738e6e287fSHans Petter Selasky return -ENOMEM;
43748e6e287fSHans Petter Selasky
43758e6e287fSHans Petter Selasky err = mlx5_core_query_sq(dev->mdev, sq->base.mqp.qpn, out);
43768e6e287fSHans Petter Selasky if (err)
43778e6e287fSHans Petter Selasky goto out;
43788e6e287fSHans Petter Selasky
43798e6e287fSHans Petter Selasky sqc = MLX5_ADDR_OF(query_sq_out, out, sq_context);
43808e6e287fSHans Petter Selasky *sq_state = MLX5_GET(sqc, sqc, state);
43818e6e287fSHans Petter Selasky sq->state = *sq_state;
43828e6e287fSHans Petter Selasky
43838e6e287fSHans Petter Selasky out:
43848e6e287fSHans Petter Selasky kvfree(out);
43858e6e287fSHans Petter Selasky return err;
43868e6e287fSHans Petter Selasky }
43878e6e287fSHans Petter Selasky
query_raw_packet_qp_rq_state(struct mlx5_ib_dev * dev,struct mlx5_ib_rq * rq,u8 * rq_state)43888e6e287fSHans Petter Selasky static int query_raw_packet_qp_rq_state(struct mlx5_ib_dev *dev,
43898e6e287fSHans Petter Selasky struct mlx5_ib_rq *rq,
43908e6e287fSHans Petter Selasky u8 *rq_state)
43918e6e287fSHans Petter Selasky {
43928e6e287fSHans Petter Selasky void *out;
43938e6e287fSHans Petter Selasky void *rqc;
43948e6e287fSHans Petter Selasky int inlen;
43958e6e287fSHans Petter Selasky int err;
43968e6e287fSHans Petter Selasky
43978e6e287fSHans Petter Selasky inlen = MLX5_ST_SZ_BYTES(query_rq_out);
43988e6e287fSHans Petter Selasky out = mlx5_vzalloc(inlen);
43998e6e287fSHans Petter Selasky if (!out)
44008e6e287fSHans Petter Selasky return -ENOMEM;
44018e6e287fSHans Petter Selasky
44028e6e287fSHans Petter Selasky err = mlx5_core_query_rq(dev->mdev, rq->base.mqp.qpn, out);
44038e6e287fSHans Petter Selasky if (err)
44048e6e287fSHans Petter Selasky goto out;
44058e6e287fSHans Petter Selasky
44068e6e287fSHans Petter Selasky rqc = MLX5_ADDR_OF(query_rq_out, out, rq_context);
44078e6e287fSHans Petter Selasky *rq_state = MLX5_GET(rqc, rqc, state);
44088e6e287fSHans Petter Selasky rq->state = *rq_state;
44098e6e287fSHans Petter Selasky
44108e6e287fSHans Petter Selasky out:
44118e6e287fSHans Petter Selasky kvfree(out);
44128e6e287fSHans Petter Selasky return err;
44138e6e287fSHans Petter Selasky }
44148e6e287fSHans Petter Selasky
sqrq_state_to_qp_state(u8 sq_state,u8 rq_state,struct mlx5_ib_qp * qp,u8 * qp_state)44158e6e287fSHans Petter Selasky static int sqrq_state_to_qp_state(u8 sq_state, u8 rq_state,
44168e6e287fSHans Petter Selasky struct mlx5_ib_qp *qp, u8 *qp_state)
44178e6e287fSHans Petter Selasky {
44188e6e287fSHans Petter Selasky static const u8 sqrq_trans[MLX5_RQ_NUM_STATE][MLX5_SQ_NUM_STATE] = {
44198e6e287fSHans Petter Selasky [MLX5_RQC_STATE_RST] = {
44208e6e287fSHans Petter Selasky [MLX5_SQC_STATE_RST] = IB_QPS_RESET,
44218e6e287fSHans Petter Selasky [MLX5_SQC_STATE_RDY] = MLX5_QP_STATE_BAD,
44228e6e287fSHans Petter Selasky [MLX5_SQC_STATE_ERR] = MLX5_QP_STATE_BAD,
44238e6e287fSHans Petter Selasky [MLX5_SQ_STATE_NA] = IB_QPS_RESET,
44248e6e287fSHans Petter Selasky },
44258e6e287fSHans Petter Selasky [MLX5_RQC_STATE_RDY] = {
44268e6e287fSHans Petter Selasky [MLX5_SQC_STATE_RST] = MLX5_QP_STATE_BAD,
44278e6e287fSHans Petter Selasky [MLX5_SQC_STATE_RDY] = MLX5_QP_STATE,
44288e6e287fSHans Petter Selasky [MLX5_SQC_STATE_ERR] = IB_QPS_SQE,
44298e6e287fSHans Petter Selasky [MLX5_SQ_STATE_NA] = MLX5_QP_STATE,
44308e6e287fSHans Petter Selasky },
44318e6e287fSHans Petter Selasky [MLX5_RQC_STATE_ERR] = {
44328e6e287fSHans Petter Selasky [MLX5_SQC_STATE_RST] = MLX5_QP_STATE_BAD,
44338e6e287fSHans Petter Selasky [MLX5_SQC_STATE_RDY] = MLX5_QP_STATE_BAD,
44348e6e287fSHans Petter Selasky [MLX5_SQC_STATE_ERR] = IB_QPS_ERR,
44358e6e287fSHans Petter Selasky [MLX5_SQ_STATE_NA] = IB_QPS_ERR,
44368e6e287fSHans Petter Selasky },
44378e6e287fSHans Petter Selasky [MLX5_RQ_STATE_NA] = {
44388e6e287fSHans Petter Selasky [MLX5_SQC_STATE_RST] = IB_QPS_RESET,
44398e6e287fSHans Petter Selasky [MLX5_SQC_STATE_RDY] = MLX5_QP_STATE,
44408e6e287fSHans Petter Selasky [MLX5_SQC_STATE_ERR] = MLX5_QP_STATE,
44418e6e287fSHans Petter Selasky [MLX5_SQ_STATE_NA] = MLX5_QP_STATE_BAD,
44428e6e287fSHans Petter Selasky },
44438e6e287fSHans Petter Selasky };
44448e6e287fSHans Petter Selasky
44458e6e287fSHans Petter Selasky *qp_state = sqrq_trans[rq_state][sq_state];
44468e6e287fSHans Petter Selasky
44478e6e287fSHans Petter Selasky if (*qp_state == MLX5_QP_STATE_BAD) {
44488e6e287fSHans Petter Selasky WARN(1, "Buggy Raw Packet QP state, SQ 0x%x state: 0x%x, RQ 0x%x state: 0x%x",
44498e6e287fSHans Petter Selasky qp->raw_packet_qp.sq.base.mqp.qpn, sq_state,
44508e6e287fSHans Petter Selasky qp->raw_packet_qp.rq.base.mqp.qpn, rq_state);
44518e6e287fSHans Petter Selasky return -EINVAL;
44528e6e287fSHans Petter Selasky }
44538e6e287fSHans Petter Selasky
44548e6e287fSHans Petter Selasky if (*qp_state == MLX5_QP_STATE)
44558e6e287fSHans Petter Selasky *qp_state = qp->state;
44568e6e287fSHans Petter Selasky
44578e6e287fSHans Petter Selasky return 0;
44588e6e287fSHans Petter Selasky }
44598e6e287fSHans Petter Selasky
query_raw_packet_qp_state(struct mlx5_ib_dev * dev,struct mlx5_ib_qp * qp,u8 * raw_packet_qp_state)44608e6e287fSHans Petter Selasky static int query_raw_packet_qp_state(struct mlx5_ib_dev *dev,
44618e6e287fSHans Petter Selasky struct mlx5_ib_qp *qp,
44628e6e287fSHans Petter Selasky u8 *raw_packet_qp_state)
44638e6e287fSHans Petter Selasky {
44648e6e287fSHans Petter Selasky struct mlx5_ib_raw_packet_qp *raw_packet_qp = &qp->raw_packet_qp;
44658e6e287fSHans Petter Selasky struct mlx5_ib_sq *sq = &raw_packet_qp->sq;
44668e6e287fSHans Petter Selasky struct mlx5_ib_rq *rq = &raw_packet_qp->rq;
44678e6e287fSHans Petter Selasky int err;
44688e6e287fSHans Petter Selasky u8 sq_state = MLX5_SQ_STATE_NA;
44698e6e287fSHans Petter Selasky u8 rq_state = MLX5_RQ_STATE_NA;
44708e6e287fSHans Petter Selasky
44718e6e287fSHans Petter Selasky if (qp->sq.wqe_cnt) {
44728e6e287fSHans Petter Selasky err = query_raw_packet_qp_sq_state(dev, sq, &sq_state);
44738e6e287fSHans Petter Selasky if (err)
44748e6e287fSHans Petter Selasky return err;
44758e6e287fSHans Petter Selasky }
44768e6e287fSHans Petter Selasky
44778e6e287fSHans Petter Selasky if (qp->rq.wqe_cnt) {
44788e6e287fSHans Petter Selasky err = query_raw_packet_qp_rq_state(dev, rq, &rq_state);
44798e6e287fSHans Petter Selasky if (err)
44808e6e287fSHans Petter Selasky return err;
44818e6e287fSHans Petter Selasky }
44828e6e287fSHans Petter Selasky
44838e6e287fSHans Petter Selasky return sqrq_state_to_qp_state(sq_state, rq_state, qp,
44848e6e287fSHans Petter Selasky raw_packet_qp_state);
44858e6e287fSHans Petter Selasky }
44868e6e287fSHans Petter Selasky
query_qp_attr(struct mlx5_ib_dev * dev,struct mlx5_ib_qp * qp,struct ib_qp_attr * qp_attr)44878e6e287fSHans Petter Selasky static int query_qp_attr(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
44888e6e287fSHans Petter Selasky struct ib_qp_attr *qp_attr)
44898e6e287fSHans Petter Selasky {
44908e6e287fSHans Petter Selasky int outlen = MLX5_ST_SZ_BYTES(query_qp_out);
449112515907SHans Petter Selasky struct mlx5_qp_context *context;
449212515907SHans Petter Selasky int mlx5_state;
44938e6e287fSHans Petter Selasky u32 *outb;
449412515907SHans Petter Selasky int err = 0;
449512515907SHans Petter Selasky
44968e6e287fSHans Petter Selasky outb = kzalloc(outlen, GFP_KERNEL);
44978e6e287fSHans Petter Selasky if (!outb)
44988e6e287fSHans Petter Selasky return -ENOMEM;
449912515907SHans Petter Selasky
4500788333d9SHans Petter Selasky err = mlx5_core_qp_query(dev->mdev, &qp->trans_qp.base.mqp, outb,
45018e6e287fSHans Petter Selasky outlen);
45028e6e287fSHans Petter Selasky if (err)
450312515907SHans Petter Selasky goto out;
45048e6e287fSHans Petter Selasky
45058e6e287fSHans Petter Selasky /* FIXME: use MLX5_GET rather than mlx5_qp_context manual struct */
45068e6e287fSHans Petter Selasky context = (struct mlx5_qp_context *)MLX5_ADDR_OF(query_qp_out, outb, qpc);
450712515907SHans Petter Selasky
450812515907SHans Petter Selasky mlx5_state = be32_to_cpu(context->flags) >> 28;
450912515907SHans Petter Selasky
451012515907SHans Petter Selasky qp->state = to_ib_qp_state(mlx5_state);
451112515907SHans Petter Selasky qp_attr->path_mtu = context->mtu_msgmax >> 5;
451212515907SHans Petter Selasky qp_attr->path_mig_state =
451312515907SHans Petter Selasky to_ib_mig_state((be32_to_cpu(context->flags) >> 11) & 0x3);
451412515907SHans Petter Selasky qp_attr->qkey = be32_to_cpu(context->qkey);
451512515907SHans Petter Selasky qp_attr->rq_psn = be32_to_cpu(context->rnr_nextrecvpsn) & 0xffffff;
451612515907SHans Petter Selasky qp_attr->sq_psn = be32_to_cpu(context->next_send_psn) & 0xffffff;
451712515907SHans Petter Selasky qp_attr->dest_qp_num = be32_to_cpu(context->log_pg_sz_remote_qpn) & 0xffffff;
451812515907SHans Petter Selasky qp_attr->qp_access_flags =
451912515907SHans Petter Selasky to_ib_qp_access_flags(be32_to_cpu(context->params2));
452012515907SHans Petter Selasky
452112515907SHans Petter Selasky if (qp->ibqp.qp_type == IB_QPT_RC || qp->ibqp.qp_type == IB_QPT_UC) {
452212515907SHans Petter Selasky to_ib_ah_attr(dev, &qp_attr->ah_attr, &context->pri_path);
452312515907SHans Petter Selasky to_ib_ah_attr(dev, &qp_attr->alt_ah_attr, &context->alt_path);
45248e6e287fSHans Petter Selasky qp_attr->alt_pkey_index =
45258e6e287fSHans Petter Selasky be16_to_cpu(context->alt_path.pkey_index);
452612515907SHans Petter Selasky qp_attr->alt_port_num = qp_attr->alt_ah_attr.port_num;
452712515907SHans Petter Selasky }
452812515907SHans Petter Selasky
452912515907SHans Petter Selasky qp_attr->pkey_index = be16_to_cpu(context->pri_path.pkey_index);
453012515907SHans Petter Selasky qp_attr->port_num = context->pri_path.port;
453112515907SHans Petter Selasky
453212515907SHans Petter Selasky /* qp_attr->en_sqd_async_notify is only applicable in modify qp */
453312515907SHans Petter Selasky qp_attr->sq_draining = mlx5_state == MLX5_QP_STATE_SQ_DRAINING;
453412515907SHans Petter Selasky
453512515907SHans Petter Selasky qp_attr->max_rd_atomic = 1 << ((be32_to_cpu(context->params1) >> 21) & 0x7);
453612515907SHans Petter Selasky
453712515907SHans Petter Selasky qp_attr->max_dest_rd_atomic =
453812515907SHans Petter Selasky 1 << ((be32_to_cpu(context->params2) >> 21) & 0x7);
453912515907SHans Petter Selasky qp_attr->min_rnr_timer =
454012515907SHans Petter Selasky (be32_to_cpu(context->rnr_nextrecvpsn) >> 24) & 0x1f;
454112515907SHans Petter Selasky qp_attr->timeout = context->pri_path.ackto_lt >> 3;
454212515907SHans Petter Selasky qp_attr->retry_cnt = (be32_to_cpu(context->params1) >> 16) & 0x7;
454312515907SHans Petter Selasky qp_attr->rnr_retry = (be32_to_cpu(context->params1) >> 13) & 0x7;
454412515907SHans Petter Selasky qp_attr->alt_timeout = context->alt_path.ackto_lt >> 3;
454512515907SHans Petter Selasky
45468e6e287fSHans Petter Selasky out:
454712515907SHans Petter Selasky kfree(outb);
45488e6e287fSHans Petter Selasky return err;
45498e6e287fSHans Petter Selasky }
45508e6e287fSHans Petter Selasky
mlx5_ib_query_qp(struct ib_qp * ibqp,struct ib_qp_attr * qp_attr,int qp_attr_mask,struct ib_qp_init_attr * qp_init_attr)45518e6e287fSHans Petter Selasky int mlx5_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
45528e6e287fSHans Petter Selasky int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr)
45538e6e287fSHans Petter Selasky {
45548e6e287fSHans Petter Selasky struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
45558e6e287fSHans Petter Selasky struct mlx5_ib_qp *qp = to_mqp(ibqp);
45568e6e287fSHans Petter Selasky int err = 0;
45578e6e287fSHans Petter Selasky u8 raw_packet_qp_state;
45588e6e287fSHans Petter Selasky
45598e6e287fSHans Petter Selasky if (ibqp->rwq_ind_tbl)
45608e6e287fSHans Petter Selasky return -ENOSYS;
45618e6e287fSHans Petter Selasky
45628e6e287fSHans Petter Selasky if (unlikely(ibqp->qp_type == IB_QPT_GSI))
45638e6e287fSHans Petter Selasky return mlx5_ib_gsi_query_qp(ibqp, qp_attr, qp_attr_mask,
45648e6e287fSHans Petter Selasky qp_init_attr);
45658e6e287fSHans Petter Selasky
45668e6e287fSHans Petter Selasky #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
45678e6e287fSHans Petter Selasky /*
45688e6e287fSHans Petter Selasky * Wait for any outstanding page faults, in case the user frees memory
45698e6e287fSHans Petter Selasky * based upon this query's result.
45708e6e287fSHans Petter Selasky */
45718e6e287fSHans Petter Selasky flush_workqueue(mlx5_ib_page_fault_wq);
45728e6e287fSHans Petter Selasky #endif
45738e6e287fSHans Petter Selasky
45748e6e287fSHans Petter Selasky mutex_lock(&qp->mutex);
45758e6e287fSHans Petter Selasky
45768e6e287fSHans Petter Selasky if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET) {
45778e6e287fSHans Petter Selasky err = query_raw_packet_qp_state(dev, qp, &raw_packet_qp_state);
45788e6e287fSHans Petter Selasky if (err)
45798e6e287fSHans Petter Selasky goto out;
45808e6e287fSHans Petter Selasky qp->state = raw_packet_qp_state;
45818e6e287fSHans Petter Selasky qp_attr->port_num = 1;
45828e6e287fSHans Petter Selasky } else {
45838e6e287fSHans Petter Selasky err = query_qp_attr(dev, qp, qp_attr);
45848e6e287fSHans Petter Selasky if (err)
45858e6e287fSHans Petter Selasky goto out;
458612515907SHans Petter Selasky }
458712515907SHans Petter Selasky
458812515907SHans Petter Selasky qp_attr->qp_state = qp->state;
458912515907SHans Petter Selasky qp_attr->cur_qp_state = qp_attr->qp_state;
459012515907SHans Petter Selasky qp_attr->cap.max_recv_wr = qp->rq.wqe_cnt;
459112515907SHans Petter Selasky qp_attr->cap.max_recv_sge = qp->rq.max_gs;
459212515907SHans Petter Selasky
459312515907SHans Petter Selasky if (!ibqp->uobject) {
459412515907SHans Petter Selasky qp_attr->cap.max_send_wr = qp->sq.max_post;
459512515907SHans Petter Selasky qp_attr->cap.max_send_sge = qp->sq.max_gs;
459612515907SHans Petter Selasky qp_init_attr->qp_context = ibqp->qp_context;
459712515907SHans Petter Selasky } else {
459812515907SHans Petter Selasky qp_attr->cap.max_send_wr = 0;
459912515907SHans Petter Selasky qp_attr->cap.max_send_sge = 0;
460012515907SHans Petter Selasky }
460112515907SHans Petter Selasky
460212515907SHans Petter Selasky qp_init_attr->qp_type = ibqp->qp_type;
460312515907SHans Petter Selasky qp_init_attr->recv_cq = ibqp->recv_cq;
460412515907SHans Petter Selasky qp_init_attr->send_cq = ibqp->send_cq;
460512515907SHans Petter Selasky qp_init_attr->srq = ibqp->srq;
460612515907SHans Petter Selasky qp_attr->cap.max_inline_data = qp->max_inline_data;
460712515907SHans Petter Selasky
460812515907SHans Petter Selasky qp_init_attr->cap = qp_attr->cap;
460912515907SHans Petter Selasky
461012515907SHans Petter Selasky qp_init_attr->create_flags = 0;
461112515907SHans Petter Selasky if (qp->flags & MLX5_IB_QP_BLOCK_MULTICAST_LOOPBACK)
461212515907SHans Petter Selasky qp_init_attr->create_flags |= IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK;
461312515907SHans Petter Selasky
46148e6e287fSHans Petter Selasky if (qp->flags & MLX5_IB_QP_CROSS_CHANNEL)
46158e6e287fSHans Petter Selasky qp_init_attr->create_flags |= IB_QP_CREATE_CROSS_CHANNEL;
46168e6e287fSHans Petter Selasky if (qp->flags & MLX5_IB_QP_MANAGED_SEND)
46178e6e287fSHans Petter Selasky qp_init_attr->create_flags |= IB_QP_CREATE_MANAGED_SEND;
46188e6e287fSHans Petter Selasky if (qp->flags & MLX5_IB_QP_MANAGED_RECV)
46198e6e287fSHans Petter Selasky qp_init_attr->create_flags |= IB_QP_CREATE_MANAGED_RECV;
46208e6e287fSHans Petter Selasky if (qp->flags & MLX5_IB_QP_SQPN_QP1)
4621f8f5b459SHans Petter Selasky qp_init_attr->create_flags |= MLX5_IB_QP_CREATE_SQPN_QP1;
46228e6e287fSHans Petter Selasky
462312515907SHans Petter Selasky qp_init_attr->sq_sig_type = qp->sq_signal_bits & MLX5_WQE_CTRL_CQ_UPDATE ?
462412515907SHans Petter Selasky IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
462512515907SHans Petter Selasky
462612515907SHans Petter Selasky out:
462712515907SHans Petter Selasky mutex_unlock(&qp->mutex);
462812515907SHans Petter Selasky return err;
462912515907SHans Petter Selasky }
463012515907SHans Petter Selasky
mlx5_ib_alloc_xrcd(struct ib_device * ibdev,struct ib_udata * udata)463112515907SHans Petter Selasky struct ib_xrcd *mlx5_ib_alloc_xrcd(struct ib_device *ibdev,
463212515907SHans Petter Selasky struct ib_udata *udata)
463312515907SHans Petter Selasky {
463412515907SHans Petter Selasky struct mlx5_ib_dev *dev = to_mdev(ibdev);
463512515907SHans Petter Selasky struct mlx5_ib_xrcd *xrcd;
463612515907SHans Petter Selasky int err;
463712515907SHans Petter Selasky
463812515907SHans Petter Selasky if (!MLX5_CAP_GEN(dev->mdev, xrc))
463912515907SHans Petter Selasky return ERR_PTR(-ENOSYS);
464012515907SHans Petter Selasky
464112515907SHans Petter Selasky xrcd = kmalloc(sizeof(*xrcd), GFP_KERNEL);
464212515907SHans Petter Selasky if (!xrcd)
464312515907SHans Petter Selasky return ERR_PTR(-ENOMEM);
464412515907SHans Petter Selasky
464512515907SHans Petter Selasky err = mlx5_core_xrcd_alloc(dev->mdev, &xrcd->xrcdn);
464612515907SHans Petter Selasky if (err) {
464712515907SHans Petter Selasky kfree(xrcd);
464812515907SHans Petter Selasky return ERR_PTR(-ENOMEM);
464912515907SHans Petter Selasky }
465012515907SHans Petter Selasky
465112515907SHans Petter Selasky return &xrcd->ibxrcd;
465212515907SHans Petter Selasky }
465312515907SHans Petter Selasky
mlx5_ib_dealloc_xrcd(struct ib_xrcd * xrcd,struct ib_udata * udata)4654b633e08cSHans Petter Selasky int mlx5_ib_dealloc_xrcd(struct ib_xrcd *xrcd, struct ib_udata *udata)
465512515907SHans Petter Selasky {
465612515907SHans Petter Selasky struct mlx5_ib_dev *dev = to_mdev(xrcd->device);
465712515907SHans Petter Selasky u32 xrcdn = to_mxrcd(xrcd)->xrcdn;
465812515907SHans Petter Selasky int err;
465912515907SHans Petter Selasky
466012515907SHans Petter Selasky err = mlx5_core_xrcd_dealloc(dev->mdev, xrcdn);
4661b633e08cSHans Petter Selasky if (err)
466212515907SHans Petter Selasky mlx5_ib_warn(dev, "failed to dealloc xrcdn 0x%x\n", xrcdn);
466312515907SHans Petter Selasky
466412515907SHans Petter Selasky kfree(xrcd);
466512515907SHans Petter Selasky return 0;
466612515907SHans Petter Selasky }
46678e6e287fSHans Petter Selasky
mlx5_ib_wq_event(struct mlx5_core_qp * core_qp,int type)46688e6e287fSHans Petter Selasky static void mlx5_ib_wq_event(struct mlx5_core_qp *core_qp, int type)
46698e6e287fSHans Petter Selasky {
46708e6e287fSHans Petter Selasky struct mlx5_ib_rwq *rwq = to_mibrwq(core_qp);
46718e6e287fSHans Petter Selasky struct mlx5_ib_dev *dev = to_mdev(rwq->ibwq.device);
46728e6e287fSHans Petter Selasky struct ib_event event;
46738e6e287fSHans Petter Selasky
46748e6e287fSHans Petter Selasky if (rwq->ibwq.event_handler) {
46758e6e287fSHans Petter Selasky event.device = rwq->ibwq.device;
46768e6e287fSHans Petter Selasky event.element.wq = &rwq->ibwq;
46778e6e287fSHans Petter Selasky switch (type) {
46788e6e287fSHans Petter Selasky case MLX5_EVENT_TYPE_WQ_CATAS_ERROR:
46798e6e287fSHans Petter Selasky event.event = IB_EVENT_WQ_FATAL;
46808e6e287fSHans Petter Selasky break;
46818e6e287fSHans Petter Selasky default:
46828e6e287fSHans Petter Selasky mlx5_ib_warn(dev, "Unexpected event type %d on WQ %06x\n", type, core_qp->qpn);
46838e6e287fSHans Petter Selasky return;
46848e6e287fSHans Petter Selasky }
46858e6e287fSHans Petter Selasky
46868e6e287fSHans Petter Selasky rwq->ibwq.event_handler(&event, rwq->ibwq.wq_context);
46878e6e287fSHans Petter Selasky }
46888e6e287fSHans Petter Selasky }
46898e6e287fSHans Petter Selasky
create_rq(struct mlx5_ib_rwq * rwq,struct ib_pd * pd,struct ib_wq_init_attr * init_attr)46908e6e287fSHans Petter Selasky static int create_rq(struct mlx5_ib_rwq *rwq, struct ib_pd *pd,
46918e6e287fSHans Petter Selasky struct ib_wq_init_attr *init_attr)
46928e6e287fSHans Petter Selasky {
46938e6e287fSHans Petter Selasky struct mlx5_ib_dev *dev;
46948e6e287fSHans Petter Selasky __be64 *rq_pas0;
46958e6e287fSHans Petter Selasky void *in;
46968e6e287fSHans Petter Selasky void *rqc;
46978e6e287fSHans Petter Selasky void *wq;
46988e6e287fSHans Petter Selasky int inlen;
46998e6e287fSHans Petter Selasky int err;
47008e6e287fSHans Petter Selasky
47018e6e287fSHans Petter Selasky dev = to_mdev(pd->device);
47028e6e287fSHans Petter Selasky
47038e6e287fSHans Petter Selasky inlen = MLX5_ST_SZ_BYTES(create_rq_in) + sizeof(u64) * rwq->rq_num_pas;
47048e6e287fSHans Petter Selasky in = mlx5_vzalloc(inlen);
47058e6e287fSHans Petter Selasky if (!in)
47068e6e287fSHans Petter Selasky return -ENOMEM;
47078e6e287fSHans Petter Selasky
4708b633e08cSHans Petter Selasky MLX5_SET(create_rq_in, in, uid, to_mpd(pd)->uid);
47098e6e287fSHans Petter Selasky rqc = MLX5_ADDR_OF(create_rq_in, in, ctx);
47108e6e287fSHans Petter Selasky MLX5_SET(rqc, rqc, mem_rq_type,
47118e6e287fSHans Petter Selasky MLX5_RQC_RQ_TYPE_MEMORY_RQ_INLINE);
47128e6e287fSHans Petter Selasky MLX5_SET(rqc, rqc, user_index, rwq->user_index);
47138e6e287fSHans Petter Selasky MLX5_SET(rqc, rqc, cqn, to_mcq(init_attr->cq)->mcq.cqn);
47148e6e287fSHans Petter Selasky MLX5_SET(rqc, rqc, state, MLX5_RQC_STATE_RST);
47158e6e287fSHans Petter Selasky MLX5_SET(rqc, rqc, flush_in_error_en, 1);
47168e6e287fSHans Petter Selasky wq = MLX5_ADDR_OF(rqc, rqc, wq);
47178e6e287fSHans Petter Selasky MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_CYCLIC);
47188e6e287fSHans Petter Selasky MLX5_SET(wq, wq, end_padding_mode, MLX5_WQ_END_PAD_MODE_ALIGN);
47198e6e287fSHans Petter Selasky MLX5_SET(wq, wq, log_wq_stride, rwq->log_rq_stride);
47208e6e287fSHans Petter Selasky MLX5_SET(wq, wq, log_wq_sz, rwq->log_rq_size);
47218e6e287fSHans Petter Selasky MLX5_SET(wq, wq, pd, to_mpd(pd)->pdn);
47228e6e287fSHans Petter Selasky MLX5_SET(wq, wq, page_offset, rwq->rq_page_offset);
47238e6e287fSHans Petter Selasky MLX5_SET(wq, wq, log_wq_pg_sz, rwq->log_page_size);
47248e6e287fSHans Petter Selasky MLX5_SET(wq, wq, wq_signature, rwq->wq_sig);
47258e6e287fSHans Petter Selasky MLX5_SET64(wq, wq, dbr_addr, rwq->db.dma);
47268e6e287fSHans Petter Selasky rq_pas0 = (__be64 *)MLX5_ADDR_OF(wq, wq, pas);
47278e6e287fSHans Petter Selasky mlx5_ib_populate_pas(dev, rwq->umem, rwq->page_shift, rq_pas0, 0);
47288e6e287fSHans Petter Selasky err = mlx5_core_create_rq_tracked(dev->mdev, in, inlen, &rwq->core_qp);
47298e6e287fSHans Petter Selasky kvfree(in);
47308e6e287fSHans Petter Selasky return err;
47318e6e287fSHans Petter Selasky }
47328e6e287fSHans Petter Selasky
set_user_rq_size(struct mlx5_ib_dev * dev,struct ib_wq_init_attr * wq_init_attr,struct mlx5_ib_create_wq * ucmd,struct mlx5_ib_rwq * rwq)47338e6e287fSHans Petter Selasky static int set_user_rq_size(struct mlx5_ib_dev *dev,
47348e6e287fSHans Petter Selasky struct ib_wq_init_attr *wq_init_attr,
47358e6e287fSHans Petter Selasky struct mlx5_ib_create_wq *ucmd,
47368e6e287fSHans Petter Selasky struct mlx5_ib_rwq *rwq)
47378e6e287fSHans Petter Selasky {
47388e6e287fSHans Petter Selasky /* Sanity check RQ size before proceeding */
47398e6e287fSHans Petter Selasky if (wq_init_attr->max_wr > (1 << MLX5_CAP_GEN(dev->mdev, log_max_wq_sz)))
47408e6e287fSHans Petter Selasky return -EINVAL;
47418e6e287fSHans Petter Selasky
47428e6e287fSHans Petter Selasky if (!ucmd->rq_wqe_count)
47438e6e287fSHans Petter Selasky return -EINVAL;
47448e6e287fSHans Petter Selasky
47458e6e287fSHans Petter Selasky rwq->wqe_count = ucmd->rq_wqe_count;
47468e6e287fSHans Petter Selasky rwq->wqe_shift = ucmd->rq_wqe_shift;
47478e6e287fSHans Petter Selasky rwq->buf_size = (rwq->wqe_count << rwq->wqe_shift);
47488e6e287fSHans Petter Selasky rwq->log_rq_stride = rwq->wqe_shift;
47498e6e287fSHans Petter Selasky rwq->log_rq_size = ilog2(rwq->wqe_count);
47508e6e287fSHans Petter Selasky return 0;
47518e6e287fSHans Petter Selasky }
47528e6e287fSHans Petter Selasky
prepare_user_rq(struct ib_pd * pd,struct ib_wq_init_attr * init_attr,struct ib_udata * udata,struct mlx5_ib_rwq * rwq)47538e6e287fSHans Petter Selasky static int prepare_user_rq(struct ib_pd *pd,
47548e6e287fSHans Petter Selasky struct ib_wq_init_attr *init_attr,
47558e6e287fSHans Petter Selasky struct ib_udata *udata,
47568e6e287fSHans Petter Selasky struct mlx5_ib_rwq *rwq)
47578e6e287fSHans Petter Selasky {
47588e6e287fSHans Petter Selasky struct mlx5_ib_dev *dev = to_mdev(pd->device);
47598e6e287fSHans Petter Selasky struct mlx5_ib_create_wq ucmd = {};
47608e6e287fSHans Petter Selasky int err;
47618e6e287fSHans Petter Selasky size_t required_cmd_sz;
47628e6e287fSHans Petter Selasky
47638e6e287fSHans Petter Selasky required_cmd_sz = offsetof(typeof(ucmd), reserved) + sizeof(ucmd.reserved);
47648e6e287fSHans Petter Selasky if (udata->inlen < required_cmd_sz) {
47658e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "invalid inlen\n");
47668e6e287fSHans Petter Selasky return -EINVAL;
47678e6e287fSHans Petter Selasky }
47688e6e287fSHans Petter Selasky
47698e6e287fSHans Petter Selasky if (udata->inlen > sizeof(ucmd) &&
47708e6e287fSHans Petter Selasky !ib_is_udata_cleared(udata, sizeof(ucmd),
47718e6e287fSHans Petter Selasky udata->inlen - sizeof(ucmd))) {
47728e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "inlen is not supported\n");
47738e6e287fSHans Petter Selasky return -EOPNOTSUPP;
47748e6e287fSHans Petter Selasky }
47758e6e287fSHans Petter Selasky
47768e6e287fSHans Petter Selasky if (ib_copy_from_udata(&ucmd, udata, min(sizeof(ucmd), udata->inlen))) {
47778e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "copy failed\n");
47788e6e287fSHans Petter Selasky return -EFAULT;
47798e6e287fSHans Petter Selasky }
47808e6e287fSHans Petter Selasky
47818e6e287fSHans Petter Selasky if (ucmd.comp_mask) {
47828e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "invalid comp mask\n");
47838e6e287fSHans Petter Selasky return -EOPNOTSUPP;
47848e6e287fSHans Petter Selasky }
47858e6e287fSHans Petter Selasky
47868e6e287fSHans Petter Selasky if (ucmd.reserved) {
47878e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "invalid reserved\n");
47888e6e287fSHans Petter Selasky return -EOPNOTSUPP;
47898e6e287fSHans Petter Selasky }
47908e6e287fSHans Petter Selasky
47918e6e287fSHans Petter Selasky err = set_user_rq_size(dev, init_attr, &ucmd, rwq);
47928e6e287fSHans Petter Selasky if (err) {
47938e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "err %d\n", err);
47948e6e287fSHans Petter Selasky return err;
47958e6e287fSHans Petter Selasky }
47968e6e287fSHans Petter Selasky
47978e6e287fSHans Petter Selasky err = create_user_rq(dev, pd, rwq, &ucmd);
47988e6e287fSHans Petter Selasky if (err) {
47998e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "err %d\n", err);
48008e6e287fSHans Petter Selasky if (err)
48018e6e287fSHans Petter Selasky return err;
48028e6e287fSHans Petter Selasky }
48038e6e287fSHans Petter Selasky
48048e6e287fSHans Petter Selasky rwq->user_index = ucmd.user_index;
48058e6e287fSHans Petter Selasky return 0;
48068e6e287fSHans Petter Selasky }
48078e6e287fSHans Petter Selasky
mlx5_ib_create_wq(struct ib_pd * pd,struct ib_wq_init_attr * init_attr,struct ib_udata * udata)48088e6e287fSHans Petter Selasky struct ib_wq *mlx5_ib_create_wq(struct ib_pd *pd,
48098e6e287fSHans Petter Selasky struct ib_wq_init_attr *init_attr,
48108e6e287fSHans Petter Selasky struct ib_udata *udata)
48118e6e287fSHans Petter Selasky {
48128e6e287fSHans Petter Selasky struct mlx5_ib_dev *dev;
48138e6e287fSHans Petter Selasky struct mlx5_ib_rwq *rwq;
48148e6e287fSHans Petter Selasky struct mlx5_ib_create_wq_resp resp = {};
48158e6e287fSHans Petter Selasky size_t min_resp_len;
48168e6e287fSHans Petter Selasky int err;
48178e6e287fSHans Petter Selasky
48188e6e287fSHans Petter Selasky if (!udata)
48198e6e287fSHans Petter Selasky return ERR_PTR(-ENOSYS);
48208e6e287fSHans Petter Selasky
48218e6e287fSHans Petter Selasky min_resp_len = offsetof(typeof(resp), reserved) + sizeof(resp.reserved);
48228e6e287fSHans Petter Selasky if (udata->outlen && udata->outlen < min_resp_len)
48238e6e287fSHans Petter Selasky return ERR_PTR(-EINVAL);
48248e6e287fSHans Petter Selasky
48258e6e287fSHans Petter Selasky dev = to_mdev(pd->device);
48268e6e287fSHans Petter Selasky switch (init_attr->wq_type) {
48278e6e287fSHans Petter Selasky case IB_WQT_RQ:
48288e6e287fSHans Petter Selasky rwq = kzalloc(sizeof(*rwq), GFP_KERNEL);
48298e6e287fSHans Petter Selasky if (!rwq)
48308e6e287fSHans Petter Selasky return ERR_PTR(-ENOMEM);
48318e6e287fSHans Petter Selasky err = prepare_user_rq(pd, init_attr, udata, rwq);
48328e6e287fSHans Petter Selasky if (err)
48338e6e287fSHans Petter Selasky goto err;
48348e6e287fSHans Petter Selasky err = create_rq(rwq, pd, init_attr);
48358e6e287fSHans Petter Selasky if (err)
48368e6e287fSHans Petter Selasky goto err_user_rq;
48378e6e287fSHans Petter Selasky break;
48388e6e287fSHans Petter Selasky default:
48398e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "unsupported wq type %d\n",
48408e6e287fSHans Petter Selasky init_attr->wq_type);
48418e6e287fSHans Petter Selasky return ERR_PTR(-EINVAL);
48428e6e287fSHans Petter Selasky }
48438e6e287fSHans Petter Selasky
48448e6e287fSHans Petter Selasky rwq->ibwq.wq_num = rwq->core_qp.qpn;
48458e6e287fSHans Petter Selasky rwq->ibwq.state = IB_WQS_RESET;
48468e6e287fSHans Petter Selasky if (udata->outlen) {
48478e6e287fSHans Petter Selasky resp.response_length = offsetof(typeof(resp), response_length) +
48488e6e287fSHans Petter Selasky sizeof(resp.response_length);
48498e6e287fSHans Petter Selasky err = ib_copy_to_udata(udata, &resp, resp.response_length);
48508e6e287fSHans Petter Selasky if (err)
48518e6e287fSHans Petter Selasky goto err_copy;
48528e6e287fSHans Petter Selasky }
48538e6e287fSHans Petter Selasky
48548e6e287fSHans Petter Selasky rwq->core_qp.event = mlx5_ib_wq_event;
48558e6e287fSHans Petter Selasky rwq->ibwq.event_handler = init_attr->event_handler;
48568e6e287fSHans Petter Selasky return &rwq->ibwq;
48578e6e287fSHans Petter Selasky
48588e6e287fSHans Petter Selasky err_copy:
48598e6e287fSHans Petter Selasky mlx5_core_destroy_rq_tracked(dev->mdev, &rwq->core_qp);
48608e6e287fSHans Petter Selasky err_user_rq:
4861b633e08cSHans Petter Selasky destroy_user_rq(pd, rwq, udata);
48628e6e287fSHans Petter Selasky err:
48638e6e287fSHans Petter Selasky kfree(rwq);
48648e6e287fSHans Petter Selasky return ERR_PTR(err);
48658e6e287fSHans Petter Selasky }
48668e6e287fSHans Petter Selasky
mlx5_ib_destroy_wq(struct ib_wq * wq,struct ib_udata * udata)4867b633e08cSHans Petter Selasky void mlx5_ib_destroy_wq(struct ib_wq *wq, struct ib_udata *udata)
48688e6e287fSHans Petter Selasky {
48698e6e287fSHans Petter Selasky struct mlx5_ib_dev *dev = to_mdev(wq->device);
48708e6e287fSHans Petter Selasky struct mlx5_ib_rwq *rwq = to_mrwq(wq);
48718e6e287fSHans Petter Selasky
48728e6e287fSHans Petter Selasky mlx5_core_destroy_rq_tracked(dev->mdev, &rwq->core_qp);
4873b633e08cSHans Petter Selasky destroy_user_rq(wq->pd, rwq, udata);
48748e6e287fSHans Petter Selasky kfree(rwq);
48758e6e287fSHans Petter Selasky }
48768e6e287fSHans Petter Selasky
mlx5_ib_create_rwq_ind_table(struct ib_device * device,struct ib_rwq_ind_table_init_attr * init_attr,struct ib_udata * udata)48778e6e287fSHans Petter Selasky struct ib_rwq_ind_table *mlx5_ib_create_rwq_ind_table(struct ib_device *device,
48788e6e287fSHans Petter Selasky struct ib_rwq_ind_table_init_attr *init_attr,
48798e6e287fSHans Petter Selasky struct ib_udata *udata)
48808e6e287fSHans Petter Selasky {
48818e6e287fSHans Petter Selasky struct mlx5_ib_dev *dev = to_mdev(device);
48828e6e287fSHans Petter Selasky struct mlx5_ib_rwq_ind_table *rwq_ind_tbl;
48838e6e287fSHans Petter Selasky int sz = 1 << init_attr->log_ind_tbl_size;
48848e6e287fSHans Petter Selasky struct mlx5_ib_create_rwq_ind_tbl_resp resp = {};
48858e6e287fSHans Petter Selasky size_t min_resp_len;
48868e6e287fSHans Petter Selasky int inlen;
48878e6e287fSHans Petter Selasky int err;
48888e6e287fSHans Petter Selasky int i;
48898e6e287fSHans Petter Selasky u32 *in;
48908e6e287fSHans Petter Selasky void *rqtc;
48918e6e287fSHans Petter Selasky
48928e6e287fSHans Petter Selasky if (udata->inlen > 0 &&
48938e6e287fSHans Petter Selasky !ib_is_udata_cleared(udata, 0,
48948e6e287fSHans Petter Selasky udata->inlen))
48958e6e287fSHans Petter Selasky return ERR_PTR(-EOPNOTSUPP);
48968e6e287fSHans Petter Selasky
48978e6e287fSHans Petter Selasky if (init_attr->log_ind_tbl_size >
48988e6e287fSHans Petter Selasky MLX5_CAP_GEN(dev->mdev, log_max_rqt_size)) {
48998e6e287fSHans Petter Selasky mlx5_ib_dbg(dev, "log_ind_tbl_size = %d is bigger than supported = %d\n",
49008e6e287fSHans Petter Selasky init_attr->log_ind_tbl_size,
49018e6e287fSHans Petter Selasky MLX5_CAP_GEN(dev->mdev, log_max_rqt_size));
49028e6e287fSHans Petter Selasky return ERR_PTR(-EINVAL);
49038e6e287fSHans Petter Selasky }
49048e6e287fSHans Petter Selasky
49058e6e287fSHans Petter Selasky min_resp_len = offsetof(typeof(resp), reserved) + sizeof(resp.reserved);
49068e6e287fSHans Petter Selasky if (udata->outlen && udata->outlen < min_resp_len)
49078e6e287fSHans Petter Selasky return ERR_PTR(-EINVAL);
49088e6e287fSHans Petter Selasky
49098e6e287fSHans Petter Selasky rwq_ind_tbl = kzalloc(sizeof(*rwq_ind_tbl), GFP_KERNEL);
49108e6e287fSHans Petter Selasky if (!rwq_ind_tbl)
49118e6e287fSHans Petter Selasky return ERR_PTR(-ENOMEM);
49128e6e287fSHans Petter Selasky
49138e6e287fSHans Petter Selasky inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + sizeof(u32) * sz;
49148e6e287fSHans Petter Selasky in = mlx5_vzalloc(inlen);
49158e6e287fSHans Petter Selasky if (!in) {
49168e6e287fSHans Petter Selasky err = -ENOMEM;
49178e6e287fSHans Petter Selasky goto err;
49188e6e287fSHans Petter Selasky }
49198e6e287fSHans Petter Selasky
49208e6e287fSHans Petter Selasky rqtc = MLX5_ADDR_OF(create_rqt_in, in, rqt_context);
49218e6e287fSHans Petter Selasky
49228e6e287fSHans Petter Selasky MLX5_SET(rqtc, rqtc, rqt_actual_size, sz);
49238e6e287fSHans Petter Selasky MLX5_SET(rqtc, rqtc, rqt_max_size, sz);
49248e6e287fSHans Petter Selasky
49258e6e287fSHans Petter Selasky for (i = 0; i < sz; i++)
49268e6e287fSHans Petter Selasky MLX5_SET(rqtc, rqtc, rq_num[i], init_attr->ind_tbl[i]->wq_num);
49278e6e287fSHans Petter Selasky
4928b633e08cSHans Petter Selasky rwq_ind_tbl->uid = to_mpd(init_attr->ind_tbl[0]->pd)->uid;
4929b633e08cSHans Petter Selasky MLX5_SET(create_rqt_in, in, uid, rwq_ind_tbl->uid);
4930b633e08cSHans Petter Selasky
49318e6e287fSHans Petter Selasky err = mlx5_core_create_rqt(dev->mdev, in, inlen, &rwq_ind_tbl->rqtn);
49328e6e287fSHans Petter Selasky kvfree(in);
49338e6e287fSHans Petter Selasky
49348e6e287fSHans Petter Selasky if (err)
49358e6e287fSHans Petter Selasky goto err;
49368e6e287fSHans Petter Selasky
49378e6e287fSHans Petter Selasky rwq_ind_tbl->ib_rwq_ind_tbl.ind_tbl_num = rwq_ind_tbl->rqtn;
49388e6e287fSHans Petter Selasky if (udata->outlen) {
49398e6e287fSHans Petter Selasky resp.response_length = offsetof(typeof(resp), response_length) +
49408e6e287fSHans Petter Selasky sizeof(resp.response_length);
49418e6e287fSHans Petter Selasky err = ib_copy_to_udata(udata, &resp, resp.response_length);
49428e6e287fSHans Petter Selasky if (err)
49438e6e287fSHans Petter Selasky goto err_copy;
49448e6e287fSHans Petter Selasky }
49458e6e287fSHans Petter Selasky
49468e6e287fSHans Petter Selasky return &rwq_ind_tbl->ib_rwq_ind_tbl;
49478e6e287fSHans Petter Selasky
49488e6e287fSHans Petter Selasky err_copy:
4949b633e08cSHans Petter Selasky mlx5_core_destroy_rqt(dev->mdev, rwq_ind_tbl->rqtn, rwq_ind_tbl->uid);
49508e6e287fSHans Petter Selasky err:
49518e6e287fSHans Petter Selasky kfree(rwq_ind_tbl);
49528e6e287fSHans Petter Selasky return ERR_PTR(err);
49538e6e287fSHans Petter Selasky }
49548e6e287fSHans Petter Selasky
mlx5_ib_destroy_rwq_ind_table(struct ib_rwq_ind_table * ib_rwq_ind_tbl)49558e6e287fSHans Petter Selasky int mlx5_ib_destroy_rwq_ind_table(struct ib_rwq_ind_table *ib_rwq_ind_tbl)
49568e6e287fSHans Petter Selasky {
49578e6e287fSHans Petter Selasky struct mlx5_ib_rwq_ind_table *rwq_ind_tbl = to_mrwq_ind_table(ib_rwq_ind_tbl);
49588e6e287fSHans Petter Selasky struct mlx5_ib_dev *dev = to_mdev(ib_rwq_ind_tbl->device);
49598e6e287fSHans Petter Selasky
4960b633e08cSHans Petter Selasky mlx5_core_destroy_rqt(dev->mdev, rwq_ind_tbl->rqtn, rwq_ind_tbl->uid);
49618e6e287fSHans Petter Selasky
49628e6e287fSHans Petter Selasky kfree(rwq_ind_tbl);
49638e6e287fSHans Petter Selasky return 0;
49648e6e287fSHans Petter Selasky }
49658e6e287fSHans Petter Selasky
mlx5_ib_modify_wq(struct ib_wq * wq,struct ib_wq_attr * wq_attr,u32 wq_attr_mask,struct ib_udata * udata)49668e6e287fSHans Petter Selasky int mlx5_ib_modify_wq(struct ib_wq *wq, struct ib_wq_attr *wq_attr,
49678e6e287fSHans Petter Selasky u32 wq_attr_mask, struct ib_udata *udata)
49688e6e287fSHans Petter Selasky {
49698e6e287fSHans Petter Selasky struct mlx5_ib_dev *dev = to_mdev(wq->device);
49708e6e287fSHans Petter Selasky struct mlx5_ib_rwq *rwq = to_mrwq(wq);
49718e6e287fSHans Petter Selasky struct mlx5_ib_modify_wq ucmd = {};
49728e6e287fSHans Petter Selasky size_t required_cmd_sz;
49738e6e287fSHans Petter Selasky int curr_wq_state;
49748e6e287fSHans Petter Selasky int wq_state;
49758e6e287fSHans Petter Selasky int inlen;
49768e6e287fSHans Petter Selasky int err;
49778e6e287fSHans Petter Selasky void *rqc;
49788e6e287fSHans Petter Selasky void *in;
49798e6e287fSHans Petter Selasky
49808e6e287fSHans Petter Selasky required_cmd_sz = offsetof(typeof(ucmd), reserved) + sizeof(ucmd.reserved);
49818e6e287fSHans Petter Selasky if (udata->inlen < required_cmd_sz)
49828e6e287fSHans Petter Selasky return -EINVAL;
49838e6e287fSHans Petter Selasky
49848e6e287fSHans Petter Selasky if (udata->inlen > sizeof(ucmd) &&
49858e6e287fSHans Petter Selasky !ib_is_udata_cleared(udata, sizeof(ucmd),
49868e6e287fSHans Petter Selasky udata->inlen - sizeof(ucmd)))
49878e6e287fSHans Petter Selasky return -EOPNOTSUPP;
49888e6e287fSHans Petter Selasky
49898e6e287fSHans Petter Selasky if (ib_copy_from_udata(&ucmd, udata, min(sizeof(ucmd), udata->inlen)))
49908e6e287fSHans Petter Selasky return -EFAULT;
49918e6e287fSHans Petter Selasky
49928e6e287fSHans Petter Selasky if (ucmd.comp_mask || ucmd.reserved)
49938e6e287fSHans Petter Selasky return -EOPNOTSUPP;
49948e6e287fSHans Petter Selasky
49958e6e287fSHans Petter Selasky inlen = MLX5_ST_SZ_BYTES(modify_rq_in);
49968e6e287fSHans Petter Selasky in = mlx5_vzalloc(inlen);
49978e6e287fSHans Petter Selasky if (!in)
49988e6e287fSHans Petter Selasky return -ENOMEM;
49998e6e287fSHans Petter Selasky
50008e6e287fSHans Petter Selasky rqc = MLX5_ADDR_OF(modify_rq_in, in, ctx);
50018e6e287fSHans Petter Selasky
50028e6e287fSHans Petter Selasky MLX5_SET(modify_rq_in, in, rqn, rwq->core_qp.qpn);
50038e6e287fSHans Petter Selasky curr_wq_state = (wq_attr_mask & IB_WQ_CUR_STATE) ?
50048e6e287fSHans Petter Selasky wq_attr->curr_wq_state : wq->state;
50058e6e287fSHans Petter Selasky wq_state = (wq_attr_mask & IB_WQ_STATE) ?
50068e6e287fSHans Petter Selasky wq_attr->wq_state : curr_wq_state;
50078e6e287fSHans Petter Selasky if (curr_wq_state == IB_WQS_ERR)
50088e6e287fSHans Petter Selasky curr_wq_state = MLX5_RQC_STATE_ERR;
50098e6e287fSHans Petter Selasky if (wq_state == IB_WQS_ERR)
50108e6e287fSHans Petter Selasky wq_state = MLX5_RQC_STATE_ERR;
50118e6e287fSHans Petter Selasky MLX5_SET(modify_rq_in, in, rq_state, curr_wq_state);
5012b633e08cSHans Petter Selasky MLX5_SET(modify_rq_in, in, uid, to_mpd(wq->pd)->uid);
50138e6e287fSHans Petter Selasky MLX5_SET(rqc, rqc, state, wq_state);
50148e6e287fSHans Petter Selasky
50158e6e287fSHans Petter Selasky err = mlx5_core_modify_rq(dev->mdev, in, inlen);
50168e6e287fSHans Petter Selasky kvfree(in);
50178e6e287fSHans Petter Selasky if (!err)
50188e6e287fSHans Petter Selasky rwq->ibwq.state = (wq_state == MLX5_RQC_STATE_ERR) ? IB_WQS_ERR : wq_state;
50198e6e287fSHans Petter Selasky
50208e6e287fSHans Petter Selasky return err;
50218e6e287fSHans Petter Selasky }
5022