0001
0002
0003
0004
0005
0006 #include <linux/gfp.h>
0007 #include <linux/mlx5/qp.h>
0008 #include <linux/mlx5/driver.h>
0009 #include "wr.h"
0010 #include "umr.h"
0011
0012 static const u32 mlx5_ib_opcode[] = {
0013 [IB_WR_SEND] = MLX5_OPCODE_SEND,
0014 [IB_WR_LSO] = MLX5_OPCODE_LSO,
0015 [IB_WR_SEND_WITH_IMM] = MLX5_OPCODE_SEND_IMM,
0016 [IB_WR_RDMA_WRITE] = MLX5_OPCODE_RDMA_WRITE,
0017 [IB_WR_RDMA_WRITE_WITH_IMM] = MLX5_OPCODE_RDMA_WRITE_IMM,
0018 [IB_WR_RDMA_READ] = MLX5_OPCODE_RDMA_READ,
0019 [IB_WR_ATOMIC_CMP_AND_SWP] = MLX5_OPCODE_ATOMIC_CS,
0020 [IB_WR_ATOMIC_FETCH_AND_ADD] = MLX5_OPCODE_ATOMIC_FA,
0021 [IB_WR_SEND_WITH_INV] = MLX5_OPCODE_SEND_INVAL,
0022 [IB_WR_LOCAL_INV] = MLX5_OPCODE_UMR,
0023 [IB_WR_REG_MR] = MLX5_OPCODE_UMR,
0024 [IB_WR_MASKED_ATOMIC_CMP_AND_SWP] = MLX5_OPCODE_ATOMIC_MASKED_CS,
0025 [IB_WR_MASKED_ATOMIC_FETCH_AND_ADD] = MLX5_OPCODE_ATOMIC_MASKED_FA,
0026 [MLX5_IB_WR_UMR] = MLX5_OPCODE_UMR,
0027 };
0028
0029 int mlx5r_wq_overflow(struct mlx5_ib_wq *wq, int nreq, struct ib_cq *ib_cq)
0030 {
0031 struct mlx5_ib_cq *cq;
0032 unsigned int cur;
0033
0034 cur = wq->head - wq->tail;
0035 if (likely(cur + nreq < wq->max_post))
0036 return 0;
0037
0038 cq = to_mcq(ib_cq);
0039 spin_lock(&cq->lock);
0040 cur = wq->head - wq->tail;
0041 spin_unlock(&cq->lock);
0042
0043 return cur + nreq >= wq->max_post;
0044 }
0045
0046 static __always_inline void set_raddr_seg(struct mlx5_wqe_raddr_seg *rseg,
0047 u64 remote_addr, u32 rkey)
0048 {
0049 rseg->raddr = cpu_to_be64(remote_addr);
0050 rseg->rkey = cpu_to_be32(rkey);
0051 rseg->reserved = 0;
0052 }
0053
0054 static void set_eth_seg(const struct ib_send_wr *wr, struct mlx5_ib_qp *qp,
0055 void **seg, int *size, void **cur_edge)
0056 {
0057 struct mlx5_wqe_eth_seg *eseg = *seg;
0058
0059 memset(eseg, 0, sizeof(struct mlx5_wqe_eth_seg));
0060
0061 if (wr->send_flags & IB_SEND_IP_CSUM)
0062 eseg->cs_flags = MLX5_ETH_WQE_L3_CSUM |
0063 MLX5_ETH_WQE_L4_CSUM;
0064
0065 if (wr->opcode == IB_WR_LSO) {
0066 struct ib_ud_wr *ud_wr = container_of(wr, struct ib_ud_wr, wr);
0067 size_t left, copysz;
0068 void *pdata = ud_wr->header;
0069 size_t stride;
0070
0071 left = ud_wr->hlen;
0072 eseg->mss = cpu_to_be16(ud_wr->mss);
0073 eseg->inline_hdr.sz = cpu_to_be16(left);
0074
0075
0076
0077
0078
0079 copysz = min_t(u64, *cur_edge - (void *)eseg->inline_hdr.start,
0080 left);
0081 memcpy(eseg->inline_hdr.start, pdata, copysz);
0082 stride = ALIGN(sizeof(struct mlx5_wqe_eth_seg) -
0083 sizeof(eseg->inline_hdr.start) + copysz, 16);
0084 *size += stride / 16;
0085 *seg += stride;
0086
0087 if (copysz < left) {
0088 handle_post_send_edge(&qp->sq, seg, *size, cur_edge);
0089 left -= copysz;
0090 pdata += copysz;
0091 mlx5r_memcpy_send_wqe(&qp->sq, cur_edge, seg, size,
0092 pdata, left);
0093 }
0094
0095 return;
0096 }
0097
0098 *seg += sizeof(struct mlx5_wqe_eth_seg);
0099 *size += sizeof(struct mlx5_wqe_eth_seg) / 16;
0100 }
0101
0102 static void set_datagram_seg(struct mlx5_wqe_datagram_seg *dseg,
0103 const struct ib_send_wr *wr)
0104 {
0105 memcpy(&dseg->av, &to_mah(ud_wr(wr)->ah)->av, sizeof(struct mlx5_av));
0106 dseg->av.dqp_dct =
0107 cpu_to_be32(ud_wr(wr)->remote_qpn | MLX5_EXTENDED_UD_AV);
0108 dseg->av.key.qkey.qkey = cpu_to_be32(ud_wr(wr)->remote_qkey);
0109 }
0110
0111 static void set_data_ptr_seg(struct mlx5_wqe_data_seg *dseg, struct ib_sge *sg)
0112 {
0113 dseg->byte_count = cpu_to_be32(sg->length);
0114 dseg->lkey = cpu_to_be32(sg->lkey);
0115 dseg->addr = cpu_to_be64(sg->addr);
0116 }
0117
0118 static __be64 frwr_mkey_mask(bool atomic)
0119 {
0120 u64 result;
0121
0122 result = MLX5_MKEY_MASK_LEN |
0123 MLX5_MKEY_MASK_PAGE_SIZE |
0124 MLX5_MKEY_MASK_START_ADDR |
0125 MLX5_MKEY_MASK_EN_RINVAL |
0126 MLX5_MKEY_MASK_KEY |
0127 MLX5_MKEY_MASK_LR |
0128 MLX5_MKEY_MASK_LW |
0129 MLX5_MKEY_MASK_RR |
0130 MLX5_MKEY_MASK_RW |
0131 MLX5_MKEY_MASK_SMALL_FENCE |
0132 MLX5_MKEY_MASK_FREE;
0133
0134 if (atomic)
0135 result |= MLX5_MKEY_MASK_A;
0136
0137 return cpu_to_be64(result);
0138 }
0139
0140 static __be64 sig_mkey_mask(void)
0141 {
0142 u64 result;
0143
0144 result = MLX5_MKEY_MASK_LEN |
0145 MLX5_MKEY_MASK_PAGE_SIZE |
0146 MLX5_MKEY_MASK_START_ADDR |
0147 MLX5_MKEY_MASK_EN_SIGERR |
0148 MLX5_MKEY_MASK_EN_RINVAL |
0149 MLX5_MKEY_MASK_KEY |
0150 MLX5_MKEY_MASK_LR |
0151 MLX5_MKEY_MASK_LW |
0152 MLX5_MKEY_MASK_RR |
0153 MLX5_MKEY_MASK_RW |
0154 MLX5_MKEY_MASK_SMALL_FENCE |
0155 MLX5_MKEY_MASK_FREE |
0156 MLX5_MKEY_MASK_BSF_EN;
0157
0158 return cpu_to_be64(result);
0159 }
0160
0161 static void set_reg_umr_seg(struct mlx5_wqe_umr_ctrl_seg *umr,
0162 struct mlx5_ib_mr *mr, u8 flags, bool atomic)
0163 {
0164 int size = (mr->mmkey.ndescs + mr->meta_ndescs) * mr->desc_size;
0165
0166 memset(umr, 0, sizeof(*umr));
0167
0168 umr->flags = flags;
0169 umr->xlt_octowords = cpu_to_be16(mlx5r_umr_get_xlt_octo(size));
0170 umr->mkey_mask = frwr_mkey_mask(atomic);
0171 }
0172
0173 static void set_linv_umr_seg(struct mlx5_wqe_umr_ctrl_seg *umr)
0174 {
0175 memset(umr, 0, sizeof(*umr));
0176 umr->mkey_mask = cpu_to_be64(MLX5_MKEY_MASK_FREE);
0177 umr->flags = MLX5_UMR_INLINE;
0178 }
0179
0180 static u8 get_umr_flags(int acc)
0181 {
0182 return (acc & IB_ACCESS_REMOTE_ATOMIC ? MLX5_PERM_ATOMIC : 0) |
0183 (acc & IB_ACCESS_REMOTE_WRITE ? MLX5_PERM_REMOTE_WRITE : 0) |
0184 (acc & IB_ACCESS_REMOTE_READ ? MLX5_PERM_REMOTE_READ : 0) |
0185 (acc & IB_ACCESS_LOCAL_WRITE ? MLX5_PERM_LOCAL_WRITE : 0) |
0186 MLX5_PERM_LOCAL_READ | MLX5_PERM_UMR_EN;
0187 }
0188
0189 static void set_reg_mkey_seg(struct mlx5_mkey_seg *seg,
0190 struct mlx5_ib_mr *mr,
0191 u32 key, int access)
0192 {
0193 int ndescs = ALIGN(mr->mmkey.ndescs + mr->meta_ndescs, 8) >> 1;
0194
0195 memset(seg, 0, sizeof(*seg));
0196
0197 if (mr->access_mode == MLX5_MKC_ACCESS_MODE_MTT)
0198 seg->log2_page_size = ilog2(mr->ibmr.page_size);
0199 else if (mr->access_mode == MLX5_MKC_ACCESS_MODE_KLMS)
0200
0201 ndescs *= 2;
0202
0203 seg->flags = get_umr_flags(access) | mr->access_mode;
0204 seg->qpn_mkey7_0 = cpu_to_be32((key & 0xff) | 0xffffff00);
0205 seg->flags_pd = cpu_to_be32(MLX5_MKEY_REMOTE_INVAL);
0206 seg->start_addr = cpu_to_be64(mr->ibmr.iova);
0207 seg->len = cpu_to_be64(mr->ibmr.length);
0208 seg->xlt_oct_size = cpu_to_be32(ndescs);
0209 }
0210
0211 static void set_linv_mkey_seg(struct mlx5_mkey_seg *seg)
0212 {
0213 memset(seg, 0, sizeof(*seg));
0214 seg->status = MLX5_MKEY_STATUS_FREE;
0215 }
0216
0217 static void set_reg_data_seg(struct mlx5_wqe_data_seg *dseg,
0218 struct mlx5_ib_mr *mr,
0219 struct mlx5_ib_pd *pd)
0220 {
0221 int bcount = mr->desc_size * (mr->mmkey.ndescs + mr->meta_ndescs);
0222
0223 dseg->addr = cpu_to_be64(mr->desc_map);
0224 dseg->byte_count = cpu_to_be32(ALIGN(bcount, 64));
0225 dseg->lkey = cpu_to_be32(pd->ibpd.local_dma_lkey);
0226 }
0227
0228 static __be32 send_ieth(const struct ib_send_wr *wr)
0229 {
0230 switch (wr->opcode) {
0231 case IB_WR_SEND_WITH_IMM:
0232 case IB_WR_RDMA_WRITE_WITH_IMM:
0233 return wr->ex.imm_data;
0234
0235 case IB_WR_SEND_WITH_INV:
0236 return cpu_to_be32(wr->ex.invalidate_rkey);
0237
0238 default:
0239 return 0;
0240 }
0241 }
0242
0243 static u8 calc_sig(void *wqe, int size)
0244 {
0245 u8 *p = wqe;
0246 u8 res = 0;
0247 int i;
0248
0249 for (i = 0; i < size; i++)
0250 res ^= p[i];
0251
0252 return ~res;
0253 }
0254
0255 static u8 wq_sig(void *wqe)
0256 {
0257 return calc_sig(wqe, (*((u8 *)wqe + 8) & 0x3f) << 4);
0258 }
0259
0260 static int set_data_inl_seg(struct mlx5_ib_qp *qp, const struct ib_send_wr *wr,
0261 void **wqe, int *wqe_sz, void **cur_edge)
0262 {
0263 struct mlx5_wqe_inline_seg *seg;
0264 size_t offset;
0265 int inl = 0;
0266 int i;
0267
0268 seg = *wqe;
0269 *wqe += sizeof(*seg);
0270 offset = sizeof(*seg);
0271
0272 for (i = 0; i < wr->num_sge; i++) {
0273 size_t len = wr->sg_list[i].length;
0274 void *addr = (void *)(unsigned long)(wr->sg_list[i].addr);
0275
0276 inl += len;
0277
0278 if (unlikely(inl > qp->max_inline_data))
0279 return -ENOMEM;
0280
0281 while (likely(len)) {
0282 size_t leftlen;
0283 size_t copysz;
0284
0285 handle_post_send_edge(&qp->sq, wqe,
0286 *wqe_sz + (offset >> 4),
0287 cur_edge);
0288
0289 leftlen = *cur_edge - *wqe;
0290 copysz = min_t(size_t, leftlen, len);
0291
0292 memcpy(*wqe, addr, copysz);
0293 len -= copysz;
0294 addr += copysz;
0295 *wqe += copysz;
0296 offset += copysz;
0297 }
0298 }
0299
0300 seg->byte_count = cpu_to_be32(inl | MLX5_INLINE_SEG);
0301
0302 *wqe_sz += ALIGN(inl + sizeof(seg->byte_count), 16) / 16;
0303
0304 return 0;
0305 }
0306
0307 static u16 prot_field_size(enum ib_signature_type type)
0308 {
0309 switch (type) {
0310 case IB_SIG_TYPE_T10_DIF:
0311 return MLX5_DIF_SIZE;
0312 default:
0313 return 0;
0314 }
0315 }
0316
0317 static u8 bs_selector(int block_size)
0318 {
0319 switch (block_size) {
0320 case 512: return 0x1;
0321 case 520: return 0x2;
0322 case 4096: return 0x3;
0323 case 4160: return 0x4;
0324 case 1073741824: return 0x5;
0325 default: return 0;
0326 }
0327 }
0328
0329 static void mlx5_fill_inl_bsf(struct ib_sig_domain *domain,
0330 struct mlx5_bsf_inl *inl)
0331 {
0332
0333 inl->vld_refresh = cpu_to_be16(MLX5_BSF_INL_VALID |
0334 MLX5_BSF_REFRESH_DIF);
0335 inl->dif_apptag = cpu_to_be16(domain->sig.dif.app_tag);
0336 inl->dif_reftag = cpu_to_be32(domain->sig.dif.ref_tag);
0337
0338 inl->rp_inv_seed = MLX5_BSF_REPEAT_BLOCK;
0339 inl->sig_type = domain->sig.dif.bg_type == IB_T10DIF_CRC ?
0340 MLX5_DIF_CRC : MLX5_DIF_IPCS;
0341
0342 if (domain->sig.dif.ref_remap)
0343 inl->dif_inc_ref_guard_check |= MLX5_BSF_INC_REFTAG;
0344
0345 if (domain->sig.dif.app_escape) {
0346 if (domain->sig.dif.ref_escape)
0347 inl->dif_inc_ref_guard_check |= MLX5_BSF_APPREF_ESCAPE;
0348 else
0349 inl->dif_inc_ref_guard_check |= MLX5_BSF_APPTAG_ESCAPE;
0350 }
0351
0352 inl->dif_app_bitmask_check =
0353 cpu_to_be16(domain->sig.dif.apptag_check_mask);
0354 }
0355
0356 static int mlx5_set_bsf(struct ib_mr *sig_mr,
0357 struct ib_sig_attrs *sig_attrs,
0358 struct mlx5_bsf *bsf, u32 data_size)
0359 {
0360 struct mlx5_core_sig_ctx *msig = to_mmr(sig_mr)->sig;
0361 struct mlx5_bsf_basic *basic = &bsf->basic;
0362 struct ib_sig_domain *mem = &sig_attrs->mem;
0363 struct ib_sig_domain *wire = &sig_attrs->wire;
0364
0365 memset(bsf, 0, sizeof(*bsf));
0366
0367
0368 basic->bsf_size_sbs = 1 << 7;
0369
0370 basic->check_byte_mask = sig_attrs->check_mask;
0371 basic->raw_data_size = cpu_to_be32(data_size);
0372
0373
0374 switch (sig_attrs->mem.sig_type) {
0375 case IB_SIG_TYPE_NONE:
0376 break;
0377 case IB_SIG_TYPE_T10_DIF:
0378 basic->mem.bs_selector = bs_selector(mem->sig.dif.pi_interval);
0379 basic->m_bfs_psv = cpu_to_be32(msig->psv_memory.psv_idx);
0380 mlx5_fill_inl_bsf(mem, &bsf->m_inl);
0381 break;
0382 default:
0383 return -EINVAL;
0384 }
0385
0386
0387 switch (sig_attrs->wire.sig_type) {
0388 case IB_SIG_TYPE_NONE:
0389 break;
0390 case IB_SIG_TYPE_T10_DIF:
0391 if (mem->sig.dif.pi_interval == wire->sig.dif.pi_interval &&
0392 mem->sig_type == wire->sig_type) {
0393
0394 basic->bsf_size_sbs |= 1 << 4;
0395 if (mem->sig.dif.bg_type == wire->sig.dif.bg_type)
0396 basic->wire.copy_byte_mask |= MLX5_CPY_GRD_MASK;
0397 if (mem->sig.dif.app_tag == wire->sig.dif.app_tag)
0398 basic->wire.copy_byte_mask |= MLX5_CPY_APP_MASK;
0399 if (mem->sig.dif.ref_tag == wire->sig.dif.ref_tag)
0400 basic->wire.copy_byte_mask |= MLX5_CPY_REF_MASK;
0401 } else
0402 basic->wire.bs_selector =
0403 bs_selector(wire->sig.dif.pi_interval);
0404
0405 basic->w_bfs_psv = cpu_to_be32(msig->psv_wire.psv_idx);
0406 mlx5_fill_inl_bsf(wire, &bsf->w_inl);
0407 break;
0408 default:
0409 return -EINVAL;
0410 }
0411
0412 return 0;
0413 }
0414
0415
0416 static int set_sig_data_segment(const struct ib_send_wr *send_wr,
0417 struct ib_mr *sig_mr,
0418 struct ib_sig_attrs *sig_attrs,
0419 struct mlx5_ib_qp *qp, void **seg, int *size,
0420 void **cur_edge)
0421 {
0422 struct mlx5_bsf *bsf;
0423 u32 data_len;
0424 u32 data_key;
0425 u64 data_va;
0426 u32 prot_len = 0;
0427 u32 prot_key = 0;
0428 u64 prot_va = 0;
0429 bool prot = false;
0430 int ret;
0431 int wqe_size;
0432 struct mlx5_ib_mr *mr = to_mmr(sig_mr);
0433 struct mlx5_ib_mr *pi_mr = mr->pi_mr;
0434
0435 data_len = pi_mr->data_length;
0436 data_key = pi_mr->ibmr.lkey;
0437 data_va = pi_mr->data_iova;
0438 if (pi_mr->meta_ndescs) {
0439 prot_len = pi_mr->meta_length;
0440 prot_key = pi_mr->ibmr.lkey;
0441 prot_va = pi_mr->pi_iova;
0442 prot = true;
0443 }
0444
0445 if (!prot || (data_key == prot_key && data_va == prot_va &&
0446 data_len == prot_len)) {
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457 struct mlx5_klm *data_klm = *seg;
0458
0459 data_klm->bcount = cpu_to_be32(data_len);
0460 data_klm->key = cpu_to_be32(data_key);
0461 data_klm->va = cpu_to_be64(data_va);
0462 wqe_size = ALIGN(sizeof(*data_klm), 64);
0463 } else {
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477 struct mlx5_stride_block_ctrl_seg *sblock_ctrl;
0478 struct mlx5_stride_block_entry *data_sentry;
0479 struct mlx5_stride_block_entry *prot_sentry;
0480 u16 block_size = sig_attrs->mem.sig.dif.pi_interval;
0481 int prot_size;
0482
0483 sblock_ctrl = *seg;
0484 data_sentry = (void *)sblock_ctrl + sizeof(*sblock_ctrl);
0485 prot_sentry = (void *)data_sentry + sizeof(*data_sentry);
0486
0487 prot_size = prot_field_size(sig_attrs->mem.sig_type);
0488 if (!prot_size) {
0489 pr_err("Bad block size given: %u\n", block_size);
0490 return -EINVAL;
0491 }
0492 sblock_ctrl->bcount_per_cycle = cpu_to_be32(block_size +
0493 prot_size);
0494 sblock_ctrl->op = cpu_to_be32(MLX5_STRIDE_BLOCK_OP);
0495 sblock_ctrl->repeat_count = cpu_to_be32(data_len / block_size);
0496 sblock_ctrl->num_entries = cpu_to_be16(2);
0497
0498 data_sentry->bcount = cpu_to_be16(block_size);
0499 data_sentry->key = cpu_to_be32(data_key);
0500 data_sentry->va = cpu_to_be64(data_va);
0501 data_sentry->stride = cpu_to_be16(block_size);
0502
0503 prot_sentry->bcount = cpu_to_be16(prot_size);
0504 prot_sentry->key = cpu_to_be32(prot_key);
0505 prot_sentry->va = cpu_to_be64(prot_va);
0506 prot_sentry->stride = cpu_to_be16(prot_size);
0507
0508 wqe_size = ALIGN(sizeof(*sblock_ctrl) + sizeof(*data_sentry) +
0509 sizeof(*prot_sentry), 64);
0510 }
0511
0512 *seg += wqe_size;
0513 *size += wqe_size / 16;
0514 handle_post_send_edge(&qp->sq, seg, *size, cur_edge);
0515
0516 bsf = *seg;
0517 ret = mlx5_set_bsf(sig_mr, sig_attrs, bsf, data_len);
0518 if (ret)
0519 return -EINVAL;
0520
0521 *seg += sizeof(*bsf);
0522 *size += sizeof(*bsf) / 16;
0523 handle_post_send_edge(&qp->sq, seg, *size, cur_edge);
0524
0525 return 0;
0526 }
0527
0528 static void set_sig_mkey_segment(struct mlx5_mkey_seg *seg,
0529 struct ib_mr *sig_mr, int access_flags,
0530 u32 size, u32 length, u32 pdn)
0531 {
0532 u32 sig_key = sig_mr->rkey;
0533 u8 sigerr = to_mmr(sig_mr)->sig->sigerr_count & 1;
0534
0535 memset(seg, 0, sizeof(*seg));
0536
0537 seg->flags = get_umr_flags(access_flags) | MLX5_MKC_ACCESS_MODE_KLMS;
0538 seg->qpn_mkey7_0 = cpu_to_be32((sig_key & 0xff) | 0xffffff00);
0539 seg->flags_pd = cpu_to_be32(MLX5_MKEY_REMOTE_INVAL | sigerr << 26 |
0540 MLX5_MKEY_BSF_EN | pdn);
0541 seg->len = cpu_to_be64(length);
0542 seg->xlt_oct_size = cpu_to_be32(mlx5r_umr_get_xlt_octo(size));
0543 seg->bsfs_octo_size = cpu_to_be32(MLX5_MKEY_BSF_OCTO_SIZE);
0544 }
0545
0546 static void set_sig_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr,
0547 u32 size)
0548 {
0549 memset(umr, 0, sizeof(*umr));
0550
0551 umr->flags = MLX5_FLAGS_INLINE | MLX5_FLAGS_CHECK_FREE;
0552 umr->xlt_octowords = cpu_to_be16(mlx5r_umr_get_xlt_octo(size));
0553 umr->bsf_octowords = cpu_to_be16(MLX5_MKEY_BSF_OCTO_SIZE);
0554 umr->mkey_mask = sig_mkey_mask();
0555 }
0556
0557 static int set_pi_umr_wr(const struct ib_send_wr *send_wr,
0558 struct mlx5_ib_qp *qp, void **seg, int *size,
0559 void **cur_edge)
0560 {
0561 const struct ib_reg_wr *wr = reg_wr(send_wr);
0562 struct mlx5_ib_mr *sig_mr = to_mmr(wr->mr);
0563 struct mlx5_ib_mr *pi_mr = sig_mr->pi_mr;
0564 struct ib_sig_attrs *sig_attrs = sig_mr->ibmr.sig_attrs;
0565 u32 pdn = to_mpd(qp->ibqp.pd)->pdn;
0566 u32 xlt_size;
0567 int region_len, ret;
0568
0569 if (unlikely(send_wr->num_sge != 0) ||
0570 unlikely(wr->access & IB_ACCESS_REMOTE_ATOMIC) ||
0571 unlikely(!sig_mr->sig) || unlikely(!qp->ibqp.integrity_en) ||
0572 unlikely(!sig_mr->sig->sig_status_checked))
0573 return -EINVAL;
0574
0575
0576 region_len = pi_mr->ibmr.length;
0577
0578
0579
0580
0581
0582
0583 if (sig_attrs->mem.sig_type != IB_SIG_TYPE_NONE)
0584 xlt_size = 0x30;
0585 else
0586 xlt_size = sizeof(struct mlx5_klm);
0587
0588 set_sig_umr_segment(*seg, xlt_size);
0589 *seg += sizeof(struct mlx5_wqe_umr_ctrl_seg);
0590 *size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16;
0591 handle_post_send_edge(&qp->sq, seg, *size, cur_edge);
0592
0593 set_sig_mkey_segment(*seg, wr->mr, wr->access, xlt_size, region_len,
0594 pdn);
0595 *seg += sizeof(struct mlx5_mkey_seg);
0596 *size += sizeof(struct mlx5_mkey_seg) / 16;
0597 handle_post_send_edge(&qp->sq, seg, *size, cur_edge);
0598
0599 ret = set_sig_data_segment(send_wr, wr->mr, sig_attrs, qp, seg, size,
0600 cur_edge);
0601 if (ret)
0602 return ret;
0603
0604 sig_mr->sig->sig_status_checked = false;
0605 return 0;
0606 }
0607
0608 static int set_psv_wr(struct ib_sig_domain *domain,
0609 u32 psv_idx, void **seg, int *size)
0610 {
0611 struct mlx5_seg_set_psv *psv_seg = *seg;
0612
0613 memset(psv_seg, 0, sizeof(*psv_seg));
0614 psv_seg->psv_num = cpu_to_be32(psv_idx);
0615 switch (domain->sig_type) {
0616 case IB_SIG_TYPE_NONE:
0617 break;
0618 case IB_SIG_TYPE_T10_DIF:
0619 psv_seg->transient_sig = cpu_to_be32(domain->sig.dif.bg << 16 |
0620 domain->sig.dif.app_tag);
0621 psv_seg->ref_tag = cpu_to_be32(domain->sig.dif.ref_tag);
0622 break;
0623 default:
0624 pr_err("Bad signature type (%d) is given.\n",
0625 domain->sig_type);
0626 return -EINVAL;
0627 }
0628
0629 *seg += sizeof(*psv_seg);
0630 *size += sizeof(*psv_seg) / 16;
0631
0632 return 0;
0633 }
0634
0635 static int set_reg_wr(struct mlx5_ib_qp *qp,
0636 const struct ib_reg_wr *wr,
0637 void **seg, int *size, void **cur_edge,
0638 bool check_not_free)
0639 {
0640 struct mlx5_ib_mr *mr = to_mmr(wr->mr);
0641 struct mlx5_ib_pd *pd = to_mpd(qp->ibqp.pd);
0642 struct mlx5_ib_dev *dev = to_mdev(pd->ibpd.device);
0643 int mr_list_size = (mr->mmkey.ndescs + mr->meta_ndescs) * mr->desc_size;
0644 bool umr_inline = mr_list_size <= MLX5_IB_SQ_UMR_INLINE_THRESHOLD;
0645 bool atomic = wr->access & IB_ACCESS_REMOTE_ATOMIC;
0646 u8 flags = 0;
0647
0648
0649
0650
0651
0652 if (!mlx5r_umr_can_reconfig(dev, 0, wr->access)) {
0653 mlx5_ib_warn(
0654 to_mdev(qp->ibqp.device),
0655 "Fast update for MR access flags is not possible\n");
0656 return -EINVAL;
0657 }
0658
0659 if (unlikely(wr->wr.send_flags & IB_SEND_INLINE)) {
0660 mlx5_ib_warn(to_mdev(qp->ibqp.device),
0661 "Invalid IB_SEND_INLINE send flag\n");
0662 return -EINVAL;
0663 }
0664
0665 if (check_not_free)
0666 flags |= MLX5_UMR_CHECK_NOT_FREE;
0667 if (umr_inline)
0668 flags |= MLX5_UMR_INLINE;
0669
0670 set_reg_umr_seg(*seg, mr, flags, atomic);
0671 *seg += sizeof(struct mlx5_wqe_umr_ctrl_seg);
0672 *size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16;
0673 handle_post_send_edge(&qp->sq, seg, *size, cur_edge);
0674
0675 set_reg_mkey_seg(*seg, mr, wr->key, wr->access);
0676 *seg += sizeof(struct mlx5_mkey_seg);
0677 *size += sizeof(struct mlx5_mkey_seg) / 16;
0678 handle_post_send_edge(&qp->sq, seg, *size, cur_edge);
0679
0680 if (umr_inline) {
0681 mlx5r_memcpy_send_wqe(&qp->sq, cur_edge, seg, size, mr->descs,
0682 mr_list_size);
0683 *size = ALIGN(*size, MLX5_SEND_WQE_BB >> 4);
0684 } else {
0685 set_reg_data_seg(*seg, mr, pd);
0686 *seg += sizeof(struct mlx5_wqe_data_seg);
0687 *size += (sizeof(struct mlx5_wqe_data_seg) / 16);
0688 }
0689 return 0;
0690 }
0691
0692 static void set_linv_wr(struct mlx5_ib_qp *qp, void **seg, int *size,
0693 void **cur_edge)
0694 {
0695 set_linv_umr_seg(*seg);
0696 *seg += sizeof(struct mlx5_wqe_umr_ctrl_seg);
0697 *size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16;
0698 handle_post_send_edge(&qp->sq, seg, *size, cur_edge);
0699 set_linv_mkey_seg(*seg);
0700 *seg += sizeof(struct mlx5_mkey_seg);
0701 *size += sizeof(struct mlx5_mkey_seg) / 16;
0702 handle_post_send_edge(&qp->sq, seg, *size, cur_edge);
0703 }
0704
0705 static void dump_wqe(struct mlx5_ib_qp *qp, u32 idx, int size_16)
0706 {
0707 __be32 *p = NULL;
0708 int i, j;
0709
0710 pr_debug("dump WQE index %u:\n", idx);
0711 for (i = 0, j = 0; i < size_16 * 4; i += 4, j += 4) {
0712 if ((i & 0xf) == 0) {
0713 p = mlx5_frag_buf_get_wqe(&qp->sq.fbc, idx);
0714 pr_debug("WQBB at %p:\n", (void *)p);
0715 j = 0;
0716 idx = (idx + 1) & (qp->sq.wqe_cnt - 1);
0717 }
0718 pr_debug("%08x %08x %08x %08x\n", be32_to_cpu(p[j]),
0719 be32_to_cpu(p[j + 1]), be32_to_cpu(p[j + 2]),
0720 be32_to_cpu(p[j + 3]));
0721 }
0722 }
0723
0724 int mlx5r_begin_wqe(struct mlx5_ib_qp *qp, void **seg,
0725 struct mlx5_wqe_ctrl_seg **ctrl, unsigned int *idx,
0726 int *size, void **cur_edge, int nreq, __be32 general_id,
0727 bool send_signaled, bool solicited)
0728 {
0729 if (unlikely(mlx5r_wq_overflow(&qp->sq, nreq, qp->ibqp.send_cq)))
0730 return -ENOMEM;
0731
0732 *idx = qp->sq.cur_post & (qp->sq.wqe_cnt - 1);
0733 *seg = mlx5_frag_buf_get_wqe(&qp->sq.fbc, *idx);
0734 *ctrl = *seg;
0735 *(uint32_t *)(*seg + 8) = 0;
0736 (*ctrl)->general_id = general_id;
0737 (*ctrl)->fm_ce_se = qp->sq_signal_bits |
0738 (send_signaled ? MLX5_WQE_CTRL_CQ_UPDATE : 0) |
0739 (solicited ? MLX5_WQE_CTRL_SOLICITED : 0);
0740
0741 *seg += sizeof(**ctrl);
0742 *size = sizeof(**ctrl) / 16;
0743 *cur_edge = qp->sq.cur_edge;
0744
0745 return 0;
0746 }
0747
0748 static int begin_wqe(struct mlx5_ib_qp *qp, void **seg,
0749 struct mlx5_wqe_ctrl_seg **ctrl,
0750 const struct ib_send_wr *wr, unsigned int *idx, int *size,
0751 void **cur_edge, int nreq)
0752 {
0753 return mlx5r_begin_wqe(qp, seg, ctrl, idx, size, cur_edge, nreq,
0754 send_ieth(wr), wr->send_flags & IB_SEND_SIGNALED,
0755 wr->send_flags & IB_SEND_SOLICITED);
0756 }
0757
0758 void mlx5r_finish_wqe(struct mlx5_ib_qp *qp, struct mlx5_wqe_ctrl_seg *ctrl,
0759 void *seg, u8 size, void *cur_edge, unsigned int idx,
0760 u64 wr_id, int nreq, u8 fence, u32 mlx5_opcode)
0761 {
0762 u8 opmod = 0;
0763
0764 ctrl->opmod_idx_opcode = cpu_to_be32(((u32)(qp->sq.cur_post) << 8) |
0765 mlx5_opcode | ((u32)opmod << 24));
0766 ctrl->qpn_ds = cpu_to_be32(size | (qp->trans_qp.base.mqp.qpn << 8));
0767 ctrl->fm_ce_se |= fence;
0768 if (unlikely(qp->flags_en & MLX5_QP_FLAG_SIGNATURE))
0769 ctrl->signature = wq_sig(ctrl);
0770
0771 qp->sq.wrid[idx] = wr_id;
0772 qp->sq.w_list[idx].opcode = mlx5_opcode;
0773 qp->sq.wqe_head[idx] = qp->sq.head + nreq;
0774 qp->sq.cur_post += DIV_ROUND_UP(size * 16, MLX5_SEND_WQE_BB);
0775 qp->sq.w_list[idx].next = qp->sq.cur_post;
0776
0777
0778
0779
0780 seg = PTR_ALIGN(seg, MLX5_SEND_WQE_BB);
0781 qp->sq.cur_edge = (unlikely(seg == cur_edge)) ?
0782 get_sq_edge(&qp->sq, qp->sq.cur_post &
0783 (qp->sq.wqe_cnt - 1)) :
0784 cur_edge;
0785 }
0786
0787 static void handle_rdma_op(const struct ib_send_wr *wr, void **seg, int *size)
0788 {
0789 set_raddr_seg(*seg, rdma_wr(wr)->remote_addr, rdma_wr(wr)->rkey);
0790 *seg += sizeof(struct mlx5_wqe_raddr_seg);
0791 *size += sizeof(struct mlx5_wqe_raddr_seg) / 16;
0792 }
0793
0794 static void handle_local_inv(struct mlx5_ib_qp *qp, const struct ib_send_wr *wr,
0795 struct mlx5_wqe_ctrl_seg **ctrl, void **seg,
0796 int *size, void **cur_edge, unsigned int idx)
0797 {
0798 qp->sq.wr_data[idx] = IB_WR_LOCAL_INV;
0799 (*ctrl)->imm = cpu_to_be32(wr->ex.invalidate_rkey);
0800 set_linv_wr(qp, seg, size, cur_edge);
0801 }
0802
0803 static int handle_reg_mr(struct mlx5_ib_qp *qp, const struct ib_send_wr *wr,
0804 struct mlx5_wqe_ctrl_seg **ctrl, void **seg, int *size,
0805 void **cur_edge, unsigned int idx)
0806 {
0807 qp->sq.wr_data[idx] = IB_WR_REG_MR;
0808 (*ctrl)->imm = cpu_to_be32(reg_wr(wr)->key);
0809 return set_reg_wr(qp, reg_wr(wr), seg, size, cur_edge, true);
0810 }
0811
0812 static int handle_psv(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
0813 const struct ib_send_wr *wr,
0814 struct mlx5_wqe_ctrl_seg **ctrl, void **seg, int *size,
0815 void **cur_edge, unsigned int *idx, int nreq,
0816 struct ib_sig_domain *domain, u32 psv_index,
0817 u8 next_fence)
0818 {
0819 int err;
0820
0821
0822
0823
0824 err = mlx5r_begin_wqe(qp, seg, ctrl, idx, size, cur_edge, nreq,
0825 send_ieth(wr), false, true);
0826 if (unlikely(err)) {
0827 mlx5_ib_warn(dev, "\n");
0828 err = -ENOMEM;
0829 goto out;
0830 }
0831 err = set_psv_wr(domain, psv_index, seg, size);
0832 if (unlikely(err)) {
0833 mlx5_ib_warn(dev, "\n");
0834 goto out;
0835 }
0836 mlx5r_finish_wqe(qp, *ctrl, *seg, *size, *cur_edge, *idx, wr->wr_id,
0837 nreq, next_fence, MLX5_OPCODE_SET_PSV);
0838
0839 out:
0840 return err;
0841 }
0842
0843 static int handle_reg_mr_integrity(struct mlx5_ib_dev *dev,
0844 struct mlx5_ib_qp *qp,
0845 const struct ib_send_wr *wr,
0846 struct mlx5_wqe_ctrl_seg **ctrl, void **seg,
0847 int *size, void **cur_edge,
0848 unsigned int *idx, int nreq, u8 fence,
0849 u8 next_fence)
0850 {
0851 struct mlx5_ib_mr *mr;
0852 struct mlx5_ib_mr *pi_mr;
0853 struct mlx5_ib_mr pa_pi_mr;
0854 struct ib_sig_attrs *sig_attrs;
0855 struct ib_reg_wr reg_pi_wr;
0856 int err;
0857
0858 qp->sq.wr_data[*idx] = IB_WR_REG_MR_INTEGRITY;
0859
0860 mr = to_mmr(reg_wr(wr)->mr);
0861 pi_mr = mr->pi_mr;
0862
0863 if (pi_mr) {
0864 memset(®_pi_wr, 0,
0865 sizeof(struct ib_reg_wr));
0866
0867 reg_pi_wr.mr = &pi_mr->ibmr;
0868 reg_pi_wr.access = reg_wr(wr)->access;
0869 reg_pi_wr.key = pi_mr->ibmr.rkey;
0870
0871 (*ctrl)->imm = cpu_to_be32(reg_pi_wr.key);
0872
0873 err = set_reg_wr(qp, ®_pi_wr, seg, size, cur_edge, false);
0874 if (unlikely(err))
0875 goto out;
0876
0877 mlx5r_finish_wqe(qp, *ctrl, *seg, *size, *cur_edge, *idx,
0878 wr->wr_id, nreq, fence, MLX5_OPCODE_UMR);
0879
0880 err = begin_wqe(qp, seg, ctrl, wr, idx, size, cur_edge, nreq);
0881 if (unlikely(err)) {
0882 mlx5_ib_warn(dev, "\n");
0883 err = -ENOMEM;
0884 goto out;
0885 }
0886 } else {
0887 memset(&pa_pi_mr, 0, sizeof(struct mlx5_ib_mr));
0888
0889 pa_pi_mr.ibmr.lkey = mr->ibmr.pd->local_dma_lkey;
0890 pa_pi_mr.mmkey.ndescs = mr->mmkey.ndescs;
0891 pa_pi_mr.data_length = mr->data_length;
0892 pa_pi_mr.data_iova = mr->data_iova;
0893 if (mr->meta_ndescs) {
0894 pa_pi_mr.meta_ndescs = mr->meta_ndescs;
0895 pa_pi_mr.meta_length = mr->meta_length;
0896 pa_pi_mr.pi_iova = mr->pi_iova;
0897 }
0898
0899 pa_pi_mr.ibmr.length = mr->ibmr.length;
0900 mr->pi_mr = &pa_pi_mr;
0901 }
0902 (*ctrl)->imm = cpu_to_be32(mr->ibmr.rkey);
0903
0904 err = set_pi_umr_wr(wr, qp, seg, size, cur_edge);
0905 if (unlikely(err)) {
0906 mlx5_ib_warn(dev, "\n");
0907 goto out;
0908 }
0909 mlx5r_finish_wqe(qp, *ctrl, *seg, *size, *cur_edge, *idx, wr->wr_id,
0910 nreq, fence, MLX5_OPCODE_UMR);
0911
0912 sig_attrs = mr->ibmr.sig_attrs;
0913 err = handle_psv(dev, qp, wr, ctrl, seg, size, cur_edge, idx, nreq,
0914 &sig_attrs->mem, mr->sig->psv_memory.psv_idx,
0915 next_fence);
0916 if (unlikely(err))
0917 goto out;
0918
0919 err = handle_psv(dev, qp, wr, ctrl, seg, size, cur_edge, idx, nreq,
0920 &sig_attrs->wire, mr->sig->psv_wire.psv_idx,
0921 next_fence);
0922 if (unlikely(err))
0923 goto out;
0924
0925 qp->next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
0926
0927 out:
0928 return err;
0929 }
0930
0931 static int handle_qpt_rc(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
0932 const struct ib_send_wr *wr,
0933 struct mlx5_wqe_ctrl_seg **ctrl, void **seg, int *size,
0934 void **cur_edge, unsigned int *idx, int nreq, u8 fence,
0935 u8 next_fence, int *num_sge)
0936 {
0937 int err = 0;
0938
0939 switch (wr->opcode) {
0940 case IB_WR_RDMA_READ:
0941 case IB_WR_RDMA_WRITE:
0942 case IB_WR_RDMA_WRITE_WITH_IMM:
0943 handle_rdma_op(wr, seg, size);
0944 break;
0945
0946 case IB_WR_ATOMIC_CMP_AND_SWP:
0947 case IB_WR_ATOMIC_FETCH_AND_ADD:
0948 case IB_WR_MASKED_ATOMIC_CMP_AND_SWP:
0949 mlx5_ib_warn(dev, "Atomic operations are not supported yet\n");
0950 err = -EOPNOTSUPP;
0951 goto out;
0952
0953 case IB_WR_LOCAL_INV:
0954 handle_local_inv(qp, wr, ctrl, seg, size, cur_edge, *idx);
0955 *num_sge = 0;
0956 break;
0957
0958 case IB_WR_REG_MR:
0959 err = handle_reg_mr(qp, wr, ctrl, seg, size, cur_edge, *idx);
0960 if (unlikely(err))
0961 goto out;
0962 *num_sge = 0;
0963 break;
0964
0965 case IB_WR_REG_MR_INTEGRITY:
0966 err = handle_reg_mr_integrity(dev, qp, wr, ctrl, seg, size,
0967 cur_edge, idx, nreq, fence,
0968 next_fence);
0969 if (unlikely(err))
0970 goto out;
0971 *num_sge = 0;
0972 break;
0973
0974 default:
0975 break;
0976 }
0977
0978 out:
0979 return err;
0980 }
0981
0982 static void handle_qpt_uc(const struct ib_send_wr *wr, void **seg, int *size)
0983 {
0984 switch (wr->opcode) {
0985 case IB_WR_RDMA_WRITE:
0986 case IB_WR_RDMA_WRITE_WITH_IMM:
0987 handle_rdma_op(wr, seg, size);
0988 break;
0989 default:
0990 break;
0991 }
0992 }
0993
0994 static void handle_qpt_hw_gsi(struct mlx5_ib_qp *qp,
0995 const struct ib_send_wr *wr, void **seg,
0996 int *size, void **cur_edge)
0997 {
0998 set_datagram_seg(*seg, wr);
0999 *seg += sizeof(struct mlx5_wqe_datagram_seg);
1000 *size += sizeof(struct mlx5_wqe_datagram_seg) / 16;
1001 handle_post_send_edge(&qp->sq, seg, *size, cur_edge);
1002 }
1003
1004 static void handle_qpt_ud(struct mlx5_ib_qp *qp, const struct ib_send_wr *wr,
1005 void **seg, int *size, void **cur_edge)
1006 {
1007 set_datagram_seg(*seg, wr);
1008 *seg += sizeof(struct mlx5_wqe_datagram_seg);
1009 *size += sizeof(struct mlx5_wqe_datagram_seg) / 16;
1010 handle_post_send_edge(&qp->sq, seg, *size, cur_edge);
1011
1012
1013 if (qp->flags & IB_QP_CREATE_IPOIB_UD_LSO) {
1014 struct mlx5_wqe_eth_pad *pad;
1015
1016 pad = *seg;
1017 memset(pad, 0, sizeof(struct mlx5_wqe_eth_pad));
1018 *seg += sizeof(struct mlx5_wqe_eth_pad);
1019 *size += sizeof(struct mlx5_wqe_eth_pad) / 16;
1020 set_eth_seg(wr, qp, seg, size, cur_edge);
1021 handle_post_send_edge(&qp->sq, seg, *size, cur_edge);
1022 }
1023 }
1024
1025 void mlx5r_ring_db(struct mlx5_ib_qp *qp, unsigned int nreq,
1026 struct mlx5_wqe_ctrl_seg *ctrl)
1027 {
1028 struct mlx5_bf *bf = &qp->bf;
1029
1030 qp->sq.head += nreq;
1031
1032
1033
1034
1035 wmb();
1036
1037 qp->db.db[MLX5_SND_DBR] = cpu_to_be32(qp->sq.cur_post);
1038
1039
1040
1041
1042 wmb();
1043
1044 mlx5_write64((__be32 *)ctrl, bf->bfreg->map + bf->offset);
1045
1046
1047
1048 bf->offset ^= bf->buf_size;
1049 }
1050
1051 int mlx5_ib_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr,
1052 const struct ib_send_wr **bad_wr, bool drain)
1053 {
1054 struct mlx5_wqe_ctrl_seg *ctrl = NULL;
1055 struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
1056 struct mlx5_core_dev *mdev = dev->mdev;
1057 struct mlx5_ib_qp *qp = to_mqp(ibqp);
1058 struct mlx5_wqe_xrc_seg *xrc;
1059 void *cur_edge;
1060 int size;
1061 unsigned long flags;
1062 unsigned int idx;
1063 int err = 0;
1064 int num_sge;
1065 void *seg;
1066 int nreq;
1067 int i;
1068 u8 next_fence = 0;
1069 u8 fence;
1070
1071 if (unlikely(mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR &&
1072 !drain)) {
1073 *bad_wr = wr;
1074 return -EIO;
1075 }
1076
1077 if (qp->type == IB_QPT_GSI)
1078 return mlx5_ib_gsi_post_send(ibqp, wr, bad_wr);
1079
1080 spin_lock_irqsave(&qp->sq.lock, flags);
1081
1082 for (nreq = 0; wr; nreq++, wr = wr->next) {
1083 if (unlikely(wr->opcode >= ARRAY_SIZE(mlx5_ib_opcode))) {
1084 mlx5_ib_warn(dev, "\n");
1085 err = -EINVAL;
1086 *bad_wr = wr;
1087 goto out;
1088 }
1089
1090 num_sge = wr->num_sge;
1091 if (unlikely(num_sge > qp->sq.max_gs)) {
1092 mlx5_ib_warn(dev, "\n");
1093 err = -EINVAL;
1094 *bad_wr = wr;
1095 goto out;
1096 }
1097
1098 err = begin_wqe(qp, &seg, &ctrl, wr, &idx, &size, &cur_edge,
1099 nreq);
1100 if (err) {
1101 mlx5_ib_warn(dev, "\n");
1102 err = -ENOMEM;
1103 *bad_wr = wr;
1104 goto out;
1105 }
1106
1107 if (wr->opcode == IB_WR_REG_MR ||
1108 wr->opcode == IB_WR_REG_MR_INTEGRITY) {
1109 fence = dev->umr_fence;
1110 next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
1111 } else {
1112 if (wr->send_flags & IB_SEND_FENCE) {
1113 if (qp->next_fence)
1114 fence = MLX5_FENCE_MODE_SMALL_AND_FENCE;
1115 else
1116 fence = MLX5_FENCE_MODE_FENCE;
1117 } else {
1118 fence = qp->next_fence;
1119 }
1120 }
1121
1122 switch (qp->type) {
1123 case IB_QPT_XRC_INI:
1124 xrc = seg;
1125 seg += sizeof(*xrc);
1126 size += sizeof(*xrc) / 16;
1127 fallthrough;
1128 case IB_QPT_RC:
1129 err = handle_qpt_rc(dev, qp, wr, &ctrl, &seg, &size,
1130 &cur_edge, &idx, nreq, fence,
1131 next_fence, &num_sge);
1132 if (unlikely(err)) {
1133 *bad_wr = wr;
1134 goto out;
1135 } else if (wr->opcode == IB_WR_REG_MR_INTEGRITY) {
1136 goto skip_psv;
1137 }
1138 break;
1139
1140 case IB_QPT_UC:
1141 handle_qpt_uc(wr, &seg, &size);
1142 break;
1143 case IB_QPT_SMI:
1144 if (unlikely(!dev->port_caps[qp->port - 1].has_smi)) {
1145 mlx5_ib_warn(dev, "Send SMP MADs is not allowed\n");
1146 err = -EPERM;
1147 *bad_wr = wr;
1148 goto out;
1149 }
1150 fallthrough;
1151 case MLX5_IB_QPT_HW_GSI:
1152 handle_qpt_hw_gsi(qp, wr, &seg, &size, &cur_edge);
1153 break;
1154 case IB_QPT_UD:
1155 handle_qpt_ud(qp, wr, &seg, &size, &cur_edge);
1156 break;
1157
1158 default:
1159 break;
1160 }
1161
1162 if (wr->send_flags & IB_SEND_INLINE && num_sge) {
1163 err = set_data_inl_seg(qp, wr, &seg, &size, &cur_edge);
1164 if (unlikely(err)) {
1165 mlx5_ib_warn(dev, "\n");
1166 *bad_wr = wr;
1167 goto out;
1168 }
1169 } else {
1170 for (i = 0; i < num_sge; i++) {
1171 handle_post_send_edge(&qp->sq, &seg, size,
1172 &cur_edge);
1173 if (unlikely(!wr->sg_list[i].length))
1174 continue;
1175
1176 set_data_ptr_seg(
1177 (struct mlx5_wqe_data_seg *)seg,
1178 wr->sg_list + i);
1179 size += sizeof(struct mlx5_wqe_data_seg) / 16;
1180 seg += sizeof(struct mlx5_wqe_data_seg);
1181 }
1182 }
1183
1184 qp->next_fence = next_fence;
1185 mlx5r_finish_wqe(qp, ctrl, seg, size, cur_edge, idx, wr->wr_id,
1186 nreq, fence, mlx5_ib_opcode[wr->opcode]);
1187 skip_psv:
1188 if (0)
1189 dump_wqe(qp, idx, size);
1190 }
1191
1192 out:
1193 if (likely(nreq))
1194 mlx5r_ring_db(qp, nreq, ctrl);
1195
1196 spin_unlock_irqrestore(&qp->sq.lock, flags);
1197
1198 return err;
1199 }
1200
1201 static void set_sig_seg(struct mlx5_rwqe_sig *sig, int max_gs)
1202 {
1203 sig->signature = calc_sig(sig, (max_gs + 1) << 2);
1204 }
1205
1206 int mlx5_ib_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr,
1207 const struct ib_recv_wr **bad_wr, bool drain)
1208 {
1209 struct mlx5_ib_qp *qp = to_mqp(ibqp);
1210 struct mlx5_wqe_data_seg *scat;
1211 struct mlx5_rwqe_sig *sig;
1212 struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
1213 struct mlx5_core_dev *mdev = dev->mdev;
1214 unsigned long flags;
1215 int err = 0;
1216 int nreq;
1217 int ind;
1218 int i;
1219
1220 if (unlikely(mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR &&
1221 !drain)) {
1222 *bad_wr = wr;
1223 return -EIO;
1224 }
1225
1226 if (qp->type == IB_QPT_GSI)
1227 return mlx5_ib_gsi_post_recv(ibqp, wr, bad_wr);
1228
1229 spin_lock_irqsave(&qp->rq.lock, flags);
1230
1231 ind = qp->rq.head & (qp->rq.wqe_cnt - 1);
1232
1233 for (nreq = 0; wr; nreq++, wr = wr->next) {
1234 if (mlx5r_wq_overflow(&qp->rq, nreq, qp->ibqp.recv_cq)) {
1235 err = -ENOMEM;
1236 *bad_wr = wr;
1237 goto out;
1238 }
1239
1240 if (unlikely(wr->num_sge > qp->rq.max_gs)) {
1241 err = -EINVAL;
1242 *bad_wr = wr;
1243 goto out;
1244 }
1245
1246 scat = mlx5_frag_buf_get_wqe(&qp->rq.fbc, ind);
1247 if (qp->flags_en & MLX5_QP_FLAG_SIGNATURE)
1248 scat++;
1249
1250 for (i = 0; i < wr->num_sge; i++)
1251 set_data_ptr_seg(scat + i, wr->sg_list + i);
1252
1253 if (i < qp->rq.max_gs) {
1254 scat[i].byte_count = 0;
1255 scat[i].lkey = cpu_to_be32(MLX5_INVALID_LKEY);
1256 scat[i].addr = 0;
1257 }
1258
1259 if (qp->flags_en & MLX5_QP_FLAG_SIGNATURE) {
1260 sig = (struct mlx5_rwqe_sig *)scat;
1261 set_sig_seg(sig, qp->rq.max_gs);
1262 }
1263
1264 qp->rq.wrid[ind] = wr->wr_id;
1265
1266 ind = (ind + 1) & (qp->rq.wqe_cnt - 1);
1267 }
1268
1269 out:
1270 if (likely(nreq)) {
1271 qp->rq.head += nreq;
1272
1273
1274
1275
1276 wmb();
1277
1278 *qp->db.db = cpu_to_be32(qp->rq.head & 0xffff);
1279 }
1280
1281 spin_unlock_irqrestore(&qp->rq.lock, flags);
1282
1283 return err;
1284 }