18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2020, Mellanox Technologies inc. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/gfp.h> 78c2ecf20Sopenharmony_ci#include <linux/mlx5/qp.h> 88c2ecf20Sopenharmony_ci#include <linux/mlx5/driver.h> 98c2ecf20Sopenharmony_ci#include "wr.h" 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_cistatic const u32 mlx5_ib_opcode[] = { 128c2ecf20Sopenharmony_ci [IB_WR_SEND] = MLX5_OPCODE_SEND, 138c2ecf20Sopenharmony_ci [IB_WR_LSO] = MLX5_OPCODE_LSO, 148c2ecf20Sopenharmony_ci [IB_WR_SEND_WITH_IMM] = MLX5_OPCODE_SEND_IMM, 158c2ecf20Sopenharmony_ci [IB_WR_RDMA_WRITE] = MLX5_OPCODE_RDMA_WRITE, 168c2ecf20Sopenharmony_ci [IB_WR_RDMA_WRITE_WITH_IMM] = MLX5_OPCODE_RDMA_WRITE_IMM, 178c2ecf20Sopenharmony_ci [IB_WR_RDMA_READ] = MLX5_OPCODE_RDMA_READ, 188c2ecf20Sopenharmony_ci [IB_WR_ATOMIC_CMP_AND_SWP] = MLX5_OPCODE_ATOMIC_CS, 198c2ecf20Sopenharmony_ci [IB_WR_ATOMIC_FETCH_AND_ADD] = MLX5_OPCODE_ATOMIC_FA, 208c2ecf20Sopenharmony_ci [IB_WR_SEND_WITH_INV] = MLX5_OPCODE_SEND_INVAL, 218c2ecf20Sopenharmony_ci [IB_WR_LOCAL_INV] = MLX5_OPCODE_UMR, 228c2ecf20Sopenharmony_ci [IB_WR_REG_MR] = MLX5_OPCODE_UMR, 238c2ecf20Sopenharmony_ci [IB_WR_MASKED_ATOMIC_CMP_AND_SWP] = MLX5_OPCODE_ATOMIC_MASKED_CS, 248c2ecf20Sopenharmony_ci [IB_WR_MASKED_ATOMIC_FETCH_AND_ADD] = MLX5_OPCODE_ATOMIC_MASKED_FA, 258c2ecf20Sopenharmony_ci [MLX5_IB_WR_UMR] = MLX5_OPCODE_UMR, 268c2ecf20Sopenharmony_ci}; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci/* handle_post_send_edge - Check if we get to SQ edge. If yes, update to the 298c2ecf20Sopenharmony_ci * next nearby edge and get new address translation for current WQE position. 308c2ecf20Sopenharmony_ci * @sq - SQ buffer. 318c2ecf20Sopenharmony_ci * @seg: Current WQE position (16B aligned). 328c2ecf20Sopenharmony_ci * @wqe_sz: Total current WQE size [16B]. 338c2ecf20Sopenharmony_ci * @cur_edge: Updated current edge. 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_cistatic inline void handle_post_send_edge(struct mlx5_ib_wq *sq, void **seg, 368c2ecf20Sopenharmony_ci u32 wqe_sz, void **cur_edge) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci u32 idx; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci if (likely(*seg != *cur_edge)) 418c2ecf20Sopenharmony_ci return; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci idx = (sq->cur_post + (wqe_sz >> 2)) & (sq->wqe_cnt - 1); 448c2ecf20Sopenharmony_ci *cur_edge = get_sq_edge(sq, idx); 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci *seg = mlx5_frag_buf_get_wqe(&sq->fbc, idx); 478c2ecf20Sopenharmony_ci} 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci/* memcpy_send_wqe - copy data from src to WQE and update the relevant WQ's 508c2ecf20Sopenharmony_ci * pointers. At the end @seg is aligned to 16B regardless the copied size. 518c2ecf20Sopenharmony_ci * @sq - SQ buffer. 528c2ecf20Sopenharmony_ci * @cur_edge: Updated current edge. 538c2ecf20Sopenharmony_ci * @seg: Current WQE position (16B aligned). 548c2ecf20Sopenharmony_ci * @wqe_sz: Total current WQE size [16B]. 558c2ecf20Sopenharmony_ci * @src: Pointer to copy from. 568c2ecf20Sopenharmony_ci * @n: Number of bytes to copy. 578c2ecf20Sopenharmony_ci */ 588c2ecf20Sopenharmony_cistatic inline void memcpy_send_wqe(struct mlx5_ib_wq *sq, void **cur_edge, 598c2ecf20Sopenharmony_ci void **seg, u32 *wqe_sz, const void *src, 608c2ecf20Sopenharmony_ci size_t n) 618c2ecf20Sopenharmony_ci{ 628c2ecf20Sopenharmony_ci while (likely(n)) { 638c2ecf20Sopenharmony_ci size_t leftlen = *cur_edge - *seg; 648c2ecf20Sopenharmony_ci size_t copysz = min_t(size_t, leftlen, n); 658c2ecf20Sopenharmony_ci size_t stride; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci memcpy(*seg, src, copysz); 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci n -= copysz; 708c2ecf20Sopenharmony_ci src += copysz; 718c2ecf20Sopenharmony_ci stride = !n ? ALIGN(copysz, 16) : copysz; 728c2ecf20Sopenharmony_ci *seg += stride; 738c2ecf20Sopenharmony_ci *wqe_sz += stride >> 4; 748c2ecf20Sopenharmony_ci handle_post_send_edge(sq, seg, *wqe_sz, cur_edge); 758c2ecf20Sopenharmony_ci } 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic int mlx5_wq_overflow(struct mlx5_ib_wq *wq, int nreq, 798c2ecf20Sopenharmony_ci struct ib_cq *ib_cq) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci struct mlx5_ib_cq *cq; 828c2ecf20Sopenharmony_ci unsigned int cur; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci cur = wq->head - wq->tail; 858c2ecf20Sopenharmony_ci if (likely(cur + nreq < wq->max_post)) 868c2ecf20Sopenharmony_ci return 0; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci cq = to_mcq(ib_cq); 898c2ecf20Sopenharmony_ci spin_lock(&cq->lock); 908c2ecf20Sopenharmony_ci cur = wq->head - wq->tail; 918c2ecf20Sopenharmony_ci spin_unlock(&cq->lock); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci return cur + nreq >= wq->max_post; 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic __always_inline void set_raddr_seg(struct mlx5_wqe_raddr_seg *rseg, 978c2ecf20Sopenharmony_ci u64 remote_addr, u32 rkey) 988c2ecf20Sopenharmony_ci{ 998c2ecf20Sopenharmony_ci rseg->raddr = cpu_to_be64(remote_addr); 1008c2ecf20Sopenharmony_ci rseg->rkey = cpu_to_be32(rkey); 1018c2ecf20Sopenharmony_ci rseg->reserved = 0; 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cistatic void set_eth_seg(const struct ib_send_wr *wr, struct mlx5_ib_qp *qp, 1058c2ecf20Sopenharmony_ci void **seg, int *size, void **cur_edge) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci struct mlx5_wqe_eth_seg *eseg = *seg; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci memset(eseg, 0, sizeof(struct mlx5_wqe_eth_seg)); 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci if (wr->send_flags & IB_SEND_IP_CSUM) 1128c2ecf20Sopenharmony_ci eseg->cs_flags = MLX5_ETH_WQE_L3_CSUM | 1138c2ecf20Sopenharmony_ci MLX5_ETH_WQE_L4_CSUM; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci if (wr->opcode == IB_WR_LSO) { 1168c2ecf20Sopenharmony_ci struct ib_ud_wr *ud_wr = container_of(wr, struct ib_ud_wr, wr); 1178c2ecf20Sopenharmony_ci size_t left, copysz; 1188c2ecf20Sopenharmony_ci void *pdata = ud_wr->header; 1198c2ecf20Sopenharmony_ci size_t stride; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci left = ud_wr->hlen; 1228c2ecf20Sopenharmony_ci eseg->mss = cpu_to_be16(ud_wr->mss); 1238c2ecf20Sopenharmony_ci eseg->inline_hdr.sz = cpu_to_be16(left); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci /* memcpy_send_wqe should get a 16B align address. Hence, we 1268c2ecf20Sopenharmony_ci * first copy up to the current edge and then, if needed, 1278c2ecf20Sopenharmony_ci * continue to memcpy_send_wqe. 1288c2ecf20Sopenharmony_ci */ 1298c2ecf20Sopenharmony_ci copysz = min_t(u64, *cur_edge - (void *)eseg->inline_hdr.start, 1308c2ecf20Sopenharmony_ci left); 1318c2ecf20Sopenharmony_ci memcpy(eseg->inline_hdr.start, pdata, copysz); 1328c2ecf20Sopenharmony_ci stride = ALIGN(sizeof(struct mlx5_wqe_eth_seg) - 1338c2ecf20Sopenharmony_ci sizeof(eseg->inline_hdr.start) + copysz, 16); 1348c2ecf20Sopenharmony_ci *size += stride / 16; 1358c2ecf20Sopenharmony_ci *seg += stride; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci if (copysz < left) { 1388c2ecf20Sopenharmony_ci handle_post_send_edge(&qp->sq, seg, *size, cur_edge); 1398c2ecf20Sopenharmony_ci left -= copysz; 1408c2ecf20Sopenharmony_ci pdata += copysz; 1418c2ecf20Sopenharmony_ci memcpy_send_wqe(&qp->sq, cur_edge, seg, size, pdata, 1428c2ecf20Sopenharmony_ci left); 1438c2ecf20Sopenharmony_ci } 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci return; 1468c2ecf20Sopenharmony_ci } 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci *seg += sizeof(struct mlx5_wqe_eth_seg); 1498c2ecf20Sopenharmony_ci *size += sizeof(struct mlx5_wqe_eth_seg) / 16; 1508c2ecf20Sopenharmony_ci} 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cistatic void set_datagram_seg(struct mlx5_wqe_datagram_seg *dseg, 1538c2ecf20Sopenharmony_ci const struct ib_send_wr *wr) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci memcpy(&dseg->av, &to_mah(ud_wr(wr)->ah)->av, sizeof(struct mlx5_av)); 1568c2ecf20Sopenharmony_ci dseg->av.dqp_dct = 1578c2ecf20Sopenharmony_ci cpu_to_be32(ud_wr(wr)->remote_qpn | MLX5_EXTENDED_UD_AV); 1588c2ecf20Sopenharmony_ci dseg->av.key.qkey.qkey = cpu_to_be32(ud_wr(wr)->remote_qkey); 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cistatic void set_data_ptr_seg(struct mlx5_wqe_data_seg *dseg, struct ib_sge *sg) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci dseg->byte_count = cpu_to_be32(sg->length); 1648c2ecf20Sopenharmony_ci dseg->lkey = cpu_to_be32(sg->lkey); 1658c2ecf20Sopenharmony_ci dseg->addr = cpu_to_be64(sg->addr); 1668c2ecf20Sopenharmony_ci} 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cistatic u64 get_xlt_octo(u64 bytes) 1698c2ecf20Sopenharmony_ci{ 1708c2ecf20Sopenharmony_ci return ALIGN(bytes, MLX5_IB_UMR_XLT_ALIGNMENT) / 1718c2ecf20Sopenharmony_ci MLX5_IB_UMR_OCTOWORD; 1728c2ecf20Sopenharmony_ci} 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_cistatic __be64 frwr_mkey_mask(bool atomic) 1758c2ecf20Sopenharmony_ci{ 1768c2ecf20Sopenharmony_ci u64 result; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci result = MLX5_MKEY_MASK_LEN | 1798c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_PAGE_SIZE | 1808c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_START_ADDR | 1818c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_EN_RINVAL | 1828c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_KEY | 1838c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_LR | 1848c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_LW | 1858c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_RR | 1868c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_RW | 1878c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_SMALL_FENCE | 1888c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_FREE; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci if (atomic) 1918c2ecf20Sopenharmony_ci result |= MLX5_MKEY_MASK_A; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci return cpu_to_be64(result); 1948c2ecf20Sopenharmony_ci} 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_cistatic __be64 sig_mkey_mask(void) 1978c2ecf20Sopenharmony_ci{ 1988c2ecf20Sopenharmony_ci u64 result; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci result = MLX5_MKEY_MASK_LEN | 2018c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_PAGE_SIZE | 2028c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_START_ADDR | 2038c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_EN_SIGERR | 2048c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_EN_RINVAL | 2058c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_KEY | 2068c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_LR | 2078c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_LW | 2088c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_RR | 2098c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_RW | 2108c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_SMALL_FENCE | 2118c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_FREE | 2128c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_BSF_EN; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci return cpu_to_be64(result); 2158c2ecf20Sopenharmony_ci} 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_cistatic void set_reg_umr_seg(struct mlx5_wqe_umr_ctrl_seg *umr, 2188c2ecf20Sopenharmony_ci struct mlx5_ib_mr *mr, u8 flags, bool atomic) 2198c2ecf20Sopenharmony_ci{ 2208c2ecf20Sopenharmony_ci int size = (mr->ndescs + mr->meta_ndescs) * mr->desc_size; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci memset(umr, 0, sizeof(*umr)); 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci umr->flags = flags; 2258c2ecf20Sopenharmony_ci umr->xlt_octowords = cpu_to_be16(get_xlt_octo(size)); 2268c2ecf20Sopenharmony_ci umr->mkey_mask = frwr_mkey_mask(atomic); 2278c2ecf20Sopenharmony_ci} 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_cistatic void set_linv_umr_seg(struct mlx5_wqe_umr_ctrl_seg *umr) 2308c2ecf20Sopenharmony_ci{ 2318c2ecf20Sopenharmony_ci memset(umr, 0, sizeof(*umr)); 2328c2ecf20Sopenharmony_ci umr->mkey_mask = cpu_to_be64(MLX5_MKEY_MASK_FREE); 2338c2ecf20Sopenharmony_ci umr->flags = MLX5_UMR_INLINE; 2348c2ecf20Sopenharmony_ci} 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_cistatic __be64 get_umr_enable_mr_mask(void) 2378c2ecf20Sopenharmony_ci{ 2388c2ecf20Sopenharmony_ci u64 result; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci result = MLX5_MKEY_MASK_KEY | 2418c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_FREE; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci return cpu_to_be64(result); 2448c2ecf20Sopenharmony_ci} 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_cistatic __be64 get_umr_disable_mr_mask(void) 2478c2ecf20Sopenharmony_ci{ 2488c2ecf20Sopenharmony_ci u64 result; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci result = MLX5_MKEY_MASK_FREE; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci return cpu_to_be64(result); 2538c2ecf20Sopenharmony_ci} 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_cistatic __be64 get_umr_update_translation_mask(void) 2568c2ecf20Sopenharmony_ci{ 2578c2ecf20Sopenharmony_ci u64 result; 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci result = MLX5_MKEY_MASK_LEN | 2608c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_PAGE_SIZE | 2618c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_START_ADDR; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci return cpu_to_be64(result); 2648c2ecf20Sopenharmony_ci} 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_cistatic __be64 get_umr_update_access_mask(int atomic, 2678c2ecf20Sopenharmony_ci int relaxed_ordering_write, 2688c2ecf20Sopenharmony_ci int relaxed_ordering_read) 2698c2ecf20Sopenharmony_ci{ 2708c2ecf20Sopenharmony_ci u64 result; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci result = MLX5_MKEY_MASK_LR | 2738c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_LW | 2748c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_RR | 2758c2ecf20Sopenharmony_ci MLX5_MKEY_MASK_RW; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci if (atomic) 2788c2ecf20Sopenharmony_ci result |= MLX5_MKEY_MASK_A; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci if (relaxed_ordering_write) 2818c2ecf20Sopenharmony_ci result |= MLX5_MKEY_MASK_RELAXED_ORDERING_WRITE; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci if (relaxed_ordering_read) 2848c2ecf20Sopenharmony_ci result |= MLX5_MKEY_MASK_RELAXED_ORDERING_READ; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci return cpu_to_be64(result); 2878c2ecf20Sopenharmony_ci} 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_cistatic __be64 get_umr_update_pd_mask(void) 2908c2ecf20Sopenharmony_ci{ 2918c2ecf20Sopenharmony_ci u64 result; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci result = MLX5_MKEY_MASK_PD; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci return cpu_to_be64(result); 2968c2ecf20Sopenharmony_ci} 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistatic int umr_check_mkey_mask(struct mlx5_ib_dev *dev, u64 mask) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci if (mask & MLX5_MKEY_MASK_PAGE_SIZE && 3018c2ecf20Sopenharmony_ci MLX5_CAP_GEN(dev->mdev, umr_modify_entity_size_disabled)) 3028c2ecf20Sopenharmony_ci return -EPERM; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci if (mask & MLX5_MKEY_MASK_A && 3058c2ecf20Sopenharmony_ci MLX5_CAP_GEN(dev->mdev, umr_modify_atomic_disabled)) 3068c2ecf20Sopenharmony_ci return -EPERM; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci if (mask & MLX5_MKEY_MASK_RELAXED_ORDERING_WRITE && 3098c2ecf20Sopenharmony_ci !MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write_umr)) 3108c2ecf20Sopenharmony_ci return -EPERM; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci if (mask & MLX5_MKEY_MASK_RELAXED_ORDERING_READ && 3138c2ecf20Sopenharmony_ci !MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read_umr)) 3148c2ecf20Sopenharmony_ci return -EPERM; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci return 0; 3178c2ecf20Sopenharmony_ci} 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_cistatic int set_reg_umr_segment(struct mlx5_ib_dev *dev, 3208c2ecf20Sopenharmony_ci struct mlx5_wqe_umr_ctrl_seg *umr, 3218c2ecf20Sopenharmony_ci const struct ib_send_wr *wr) 3228c2ecf20Sopenharmony_ci{ 3238c2ecf20Sopenharmony_ci const struct mlx5_umr_wr *umrwr = umr_wr(wr); 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci memset(umr, 0, sizeof(*umr)); 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci if (!umrwr->ignore_free_state) { 3288c2ecf20Sopenharmony_ci if (wr->send_flags & MLX5_IB_SEND_UMR_FAIL_IF_FREE) 3298c2ecf20Sopenharmony_ci /* fail if free */ 3308c2ecf20Sopenharmony_ci umr->flags = MLX5_UMR_CHECK_FREE; 3318c2ecf20Sopenharmony_ci else 3328c2ecf20Sopenharmony_ci /* fail if not free */ 3338c2ecf20Sopenharmony_ci umr->flags = MLX5_UMR_CHECK_NOT_FREE; 3348c2ecf20Sopenharmony_ci } 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci umr->xlt_octowords = cpu_to_be16(get_xlt_octo(umrwr->xlt_size)); 3378c2ecf20Sopenharmony_ci if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_XLT) { 3388c2ecf20Sopenharmony_ci u64 offset = get_xlt_octo(umrwr->offset); 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci umr->xlt_offset = cpu_to_be16(offset & 0xffff); 3418c2ecf20Sopenharmony_ci umr->xlt_offset_47_16 = cpu_to_be32(offset >> 16); 3428c2ecf20Sopenharmony_ci umr->flags |= MLX5_UMR_TRANSLATION_OFFSET_EN; 3438c2ecf20Sopenharmony_ci } 3448c2ecf20Sopenharmony_ci if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_TRANSLATION) 3458c2ecf20Sopenharmony_ci umr->mkey_mask |= get_umr_update_translation_mask(); 3468c2ecf20Sopenharmony_ci if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_PD_ACCESS) { 3478c2ecf20Sopenharmony_ci umr->mkey_mask |= get_umr_update_access_mask( 3488c2ecf20Sopenharmony_ci !!(MLX5_CAP_GEN(dev->mdev, atomic)), 3498c2ecf20Sopenharmony_ci !!(MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write_umr)), 3508c2ecf20Sopenharmony_ci !!(MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read_umr))); 3518c2ecf20Sopenharmony_ci umr->mkey_mask |= get_umr_update_pd_mask(); 3528c2ecf20Sopenharmony_ci } 3538c2ecf20Sopenharmony_ci if (wr->send_flags & MLX5_IB_SEND_UMR_ENABLE_MR) 3548c2ecf20Sopenharmony_ci umr->mkey_mask |= get_umr_enable_mr_mask(); 3558c2ecf20Sopenharmony_ci if (wr->send_flags & MLX5_IB_SEND_UMR_DISABLE_MR) 3568c2ecf20Sopenharmony_ci umr->mkey_mask |= get_umr_disable_mr_mask(); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci if (!wr->num_sge) 3598c2ecf20Sopenharmony_ci umr->flags |= MLX5_UMR_INLINE; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci return umr_check_mkey_mask(dev, be64_to_cpu(umr->mkey_mask)); 3628c2ecf20Sopenharmony_ci} 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_cistatic u8 get_umr_flags(int acc) 3658c2ecf20Sopenharmony_ci{ 3668c2ecf20Sopenharmony_ci return (acc & IB_ACCESS_REMOTE_ATOMIC ? MLX5_PERM_ATOMIC : 0) | 3678c2ecf20Sopenharmony_ci (acc & IB_ACCESS_REMOTE_WRITE ? MLX5_PERM_REMOTE_WRITE : 0) | 3688c2ecf20Sopenharmony_ci (acc & IB_ACCESS_REMOTE_READ ? MLX5_PERM_REMOTE_READ : 0) | 3698c2ecf20Sopenharmony_ci (acc & IB_ACCESS_LOCAL_WRITE ? MLX5_PERM_LOCAL_WRITE : 0) | 3708c2ecf20Sopenharmony_ci MLX5_PERM_LOCAL_READ | MLX5_PERM_UMR_EN; 3718c2ecf20Sopenharmony_ci} 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_cistatic void set_reg_mkey_seg(struct mlx5_mkey_seg *seg, 3748c2ecf20Sopenharmony_ci struct mlx5_ib_mr *mr, 3758c2ecf20Sopenharmony_ci u32 key, int access) 3768c2ecf20Sopenharmony_ci{ 3778c2ecf20Sopenharmony_ci int ndescs = ALIGN(mr->ndescs + mr->meta_ndescs, 8) >> 1; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci memset(seg, 0, sizeof(*seg)); 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci if (mr->access_mode == MLX5_MKC_ACCESS_MODE_MTT) 3828c2ecf20Sopenharmony_ci seg->log2_page_size = ilog2(mr->ibmr.page_size); 3838c2ecf20Sopenharmony_ci else if (mr->access_mode == MLX5_MKC_ACCESS_MODE_KLMS) 3848c2ecf20Sopenharmony_ci /* KLMs take twice the size of MTTs */ 3858c2ecf20Sopenharmony_ci ndescs *= 2; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci seg->flags = get_umr_flags(access) | mr->access_mode; 3888c2ecf20Sopenharmony_ci seg->qpn_mkey7_0 = cpu_to_be32((key & 0xff) | 0xffffff00); 3898c2ecf20Sopenharmony_ci seg->flags_pd = cpu_to_be32(MLX5_MKEY_REMOTE_INVAL); 3908c2ecf20Sopenharmony_ci seg->start_addr = cpu_to_be64(mr->ibmr.iova); 3918c2ecf20Sopenharmony_ci seg->len = cpu_to_be64(mr->ibmr.length); 3928c2ecf20Sopenharmony_ci seg->xlt_oct_size = cpu_to_be32(ndescs); 3938c2ecf20Sopenharmony_ci} 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_cistatic void set_linv_mkey_seg(struct mlx5_mkey_seg *seg) 3968c2ecf20Sopenharmony_ci{ 3978c2ecf20Sopenharmony_ci memset(seg, 0, sizeof(*seg)); 3988c2ecf20Sopenharmony_ci seg->status = MLX5_MKEY_STATUS_FREE; 3998c2ecf20Sopenharmony_ci} 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_cistatic void set_reg_mkey_segment(struct mlx5_ib_dev *dev, 4028c2ecf20Sopenharmony_ci struct mlx5_mkey_seg *seg, 4038c2ecf20Sopenharmony_ci const struct ib_send_wr *wr) 4048c2ecf20Sopenharmony_ci{ 4058c2ecf20Sopenharmony_ci const struct mlx5_umr_wr *umrwr = umr_wr(wr); 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci memset(seg, 0, sizeof(*seg)); 4088c2ecf20Sopenharmony_ci if (wr->send_flags & MLX5_IB_SEND_UMR_DISABLE_MR) 4098c2ecf20Sopenharmony_ci MLX5_SET(mkc, seg, free, 1); 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci MLX5_SET(mkc, seg, a, 4128c2ecf20Sopenharmony_ci !!(umrwr->access_flags & IB_ACCESS_REMOTE_ATOMIC)); 4138c2ecf20Sopenharmony_ci MLX5_SET(mkc, seg, rw, 4148c2ecf20Sopenharmony_ci !!(umrwr->access_flags & IB_ACCESS_REMOTE_WRITE)); 4158c2ecf20Sopenharmony_ci MLX5_SET(mkc, seg, rr, !!(umrwr->access_flags & IB_ACCESS_REMOTE_READ)); 4168c2ecf20Sopenharmony_ci MLX5_SET(mkc, seg, lw, !!(umrwr->access_flags & IB_ACCESS_LOCAL_WRITE)); 4178c2ecf20Sopenharmony_ci MLX5_SET(mkc, seg, lr, 1); 4188c2ecf20Sopenharmony_ci if (MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write_umr)) 4198c2ecf20Sopenharmony_ci MLX5_SET(mkc, seg, relaxed_ordering_write, 4208c2ecf20Sopenharmony_ci !!(umrwr->access_flags & IB_ACCESS_RELAXED_ORDERING)); 4218c2ecf20Sopenharmony_ci if (MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read_umr)) 4228c2ecf20Sopenharmony_ci MLX5_SET(mkc, seg, relaxed_ordering_read, 4238c2ecf20Sopenharmony_ci !!(umrwr->access_flags & IB_ACCESS_RELAXED_ORDERING)); 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci if (umrwr->pd) 4268c2ecf20Sopenharmony_ci MLX5_SET(mkc, seg, pd, to_mpd(umrwr->pd)->pdn); 4278c2ecf20Sopenharmony_ci if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_TRANSLATION && 4288c2ecf20Sopenharmony_ci !umrwr->length) 4298c2ecf20Sopenharmony_ci MLX5_SET(mkc, seg, length64, 1); 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci MLX5_SET64(mkc, seg, start_addr, umrwr->virt_addr); 4328c2ecf20Sopenharmony_ci MLX5_SET64(mkc, seg, len, umrwr->length); 4338c2ecf20Sopenharmony_ci MLX5_SET(mkc, seg, log_page_size, umrwr->page_shift); 4348c2ecf20Sopenharmony_ci MLX5_SET(mkc, seg, qpn, 0xffffff); 4358c2ecf20Sopenharmony_ci MLX5_SET(mkc, seg, mkey_7_0, mlx5_mkey_variant(umrwr->mkey)); 4368c2ecf20Sopenharmony_ci} 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_cistatic void set_reg_data_seg(struct mlx5_wqe_data_seg *dseg, 4398c2ecf20Sopenharmony_ci struct mlx5_ib_mr *mr, 4408c2ecf20Sopenharmony_ci struct mlx5_ib_pd *pd) 4418c2ecf20Sopenharmony_ci{ 4428c2ecf20Sopenharmony_ci int bcount = mr->desc_size * (mr->ndescs + mr->meta_ndescs); 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci dseg->addr = cpu_to_be64(mr->desc_map); 4458c2ecf20Sopenharmony_ci dseg->byte_count = cpu_to_be32(ALIGN(bcount, 64)); 4468c2ecf20Sopenharmony_ci dseg->lkey = cpu_to_be32(pd->ibpd.local_dma_lkey); 4478c2ecf20Sopenharmony_ci} 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_cistatic __be32 send_ieth(const struct ib_send_wr *wr) 4508c2ecf20Sopenharmony_ci{ 4518c2ecf20Sopenharmony_ci switch (wr->opcode) { 4528c2ecf20Sopenharmony_ci case IB_WR_SEND_WITH_IMM: 4538c2ecf20Sopenharmony_ci case IB_WR_RDMA_WRITE_WITH_IMM: 4548c2ecf20Sopenharmony_ci return wr->ex.imm_data; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci case IB_WR_SEND_WITH_INV: 4578c2ecf20Sopenharmony_ci return cpu_to_be32(wr->ex.invalidate_rkey); 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci default: 4608c2ecf20Sopenharmony_ci return 0; 4618c2ecf20Sopenharmony_ci } 4628c2ecf20Sopenharmony_ci} 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_cistatic u8 calc_sig(void *wqe, int size) 4658c2ecf20Sopenharmony_ci{ 4668c2ecf20Sopenharmony_ci u8 *p = wqe; 4678c2ecf20Sopenharmony_ci u8 res = 0; 4688c2ecf20Sopenharmony_ci int i; 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci for (i = 0; i < size; i++) 4718c2ecf20Sopenharmony_ci res ^= p[i]; 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci return ~res; 4748c2ecf20Sopenharmony_ci} 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_cistatic u8 wq_sig(void *wqe) 4778c2ecf20Sopenharmony_ci{ 4788c2ecf20Sopenharmony_ci return calc_sig(wqe, (*((u8 *)wqe + 8) & 0x3f) << 4); 4798c2ecf20Sopenharmony_ci} 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_cistatic int set_data_inl_seg(struct mlx5_ib_qp *qp, const struct ib_send_wr *wr, 4828c2ecf20Sopenharmony_ci void **wqe, int *wqe_sz, void **cur_edge) 4838c2ecf20Sopenharmony_ci{ 4848c2ecf20Sopenharmony_ci struct mlx5_wqe_inline_seg *seg; 4858c2ecf20Sopenharmony_ci size_t offset; 4868c2ecf20Sopenharmony_ci int inl = 0; 4878c2ecf20Sopenharmony_ci int i; 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci seg = *wqe; 4908c2ecf20Sopenharmony_ci *wqe += sizeof(*seg); 4918c2ecf20Sopenharmony_ci offset = sizeof(*seg); 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci for (i = 0; i < wr->num_sge; i++) { 4948c2ecf20Sopenharmony_ci size_t len = wr->sg_list[i].length; 4958c2ecf20Sopenharmony_ci void *addr = (void *)(unsigned long)(wr->sg_list[i].addr); 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci inl += len; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci if (unlikely(inl > qp->max_inline_data)) 5008c2ecf20Sopenharmony_ci return -ENOMEM; 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci while (likely(len)) { 5038c2ecf20Sopenharmony_ci size_t leftlen; 5048c2ecf20Sopenharmony_ci size_t copysz; 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci handle_post_send_edge(&qp->sq, wqe, 5078c2ecf20Sopenharmony_ci *wqe_sz + (offset >> 4), 5088c2ecf20Sopenharmony_ci cur_edge); 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci leftlen = *cur_edge - *wqe; 5118c2ecf20Sopenharmony_ci copysz = min_t(size_t, leftlen, len); 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci memcpy(*wqe, addr, copysz); 5148c2ecf20Sopenharmony_ci len -= copysz; 5158c2ecf20Sopenharmony_ci addr += copysz; 5168c2ecf20Sopenharmony_ci *wqe += copysz; 5178c2ecf20Sopenharmony_ci offset += copysz; 5188c2ecf20Sopenharmony_ci } 5198c2ecf20Sopenharmony_ci } 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci seg->byte_count = cpu_to_be32(inl | MLX5_INLINE_SEG); 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci *wqe_sz += ALIGN(inl + sizeof(seg->byte_count), 16) / 16; 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci return 0; 5268c2ecf20Sopenharmony_ci} 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_cistatic u16 prot_field_size(enum ib_signature_type type) 5298c2ecf20Sopenharmony_ci{ 5308c2ecf20Sopenharmony_ci switch (type) { 5318c2ecf20Sopenharmony_ci case IB_SIG_TYPE_T10_DIF: 5328c2ecf20Sopenharmony_ci return MLX5_DIF_SIZE; 5338c2ecf20Sopenharmony_ci default: 5348c2ecf20Sopenharmony_ci return 0; 5358c2ecf20Sopenharmony_ci } 5368c2ecf20Sopenharmony_ci} 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_cistatic u8 bs_selector(int block_size) 5398c2ecf20Sopenharmony_ci{ 5408c2ecf20Sopenharmony_ci switch (block_size) { 5418c2ecf20Sopenharmony_ci case 512: return 0x1; 5428c2ecf20Sopenharmony_ci case 520: return 0x2; 5438c2ecf20Sopenharmony_ci case 4096: return 0x3; 5448c2ecf20Sopenharmony_ci case 4160: return 0x4; 5458c2ecf20Sopenharmony_ci case 1073741824: return 0x5; 5468c2ecf20Sopenharmony_ci default: return 0; 5478c2ecf20Sopenharmony_ci } 5488c2ecf20Sopenharmony_ci} 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_cistatic void mlx5_fill_inl_bsf(struct ib_sig_domain *domain, 5518c2ecf20Sopenharmony_ci struct mlx5_bsf_inl *inl) 5528c2ecf20Sopenharmony_ci{ 5538c2ecf20Sopenharmony_ci /* Valid inline section and allow BSF refresh */ 5548c2ecf20Sopenharmony_ci inl->vld_refresh = cpu_to_be16(MLX5_BSF_INL_VALID | 5558c2ecf20Sopenharmony_ci MLX5_BSF_REFRESH_DIF); 5568c2ecf20Sopenharmony_ci inl->dif_apptag = cpu_to_be16(domain->sig.dif.app_tag); 5578c2ecf20Sopenharmony_ci inl->dif_reftag = cpu_to_be32(domain->sig.dif.ref_tag); 5588c2ecf20Sopenharmony_ci /* repeating block */ 5598c2ecf20Sopenharmony_ci inl->rp_inv_seed = MLX5_BSF_REPEAT_BLOCK; 5608c2ecf20Sopenharmony_ci inl->sig_type = domain->sig.dif.bg_type == IB_T10DIF_CRC ? 5618c2ecf20Sopenharmony_ci MLX5_DIF_CRC : MLX5_DIF_IPCS; 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci if (domain->sig.dif.ref_remap) 5648c2ecf20Sopenharmony_ci inl->dif_inc_ref_guard_check |= MLX5_BSF_INC_REFTAG; 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci if (domain->sig.dif.app_escape) { 5678c2ecf20Sopenharmony_ci if (domain->sig.dif.ref_escape) 5688c2ecf20Sopenharmony_ci inl->dif_inc_ref_guard_check |= MLX5_BSF_APPREF_ESCAPE; 5698c2ecf20Sopenharmony_ci else 5708c2ecf20Sopenharmony_ci inl->dif_inc_ref_guard_check |= MLX5_BSF_APPTAG_ESCAPE; 5718c2ecf20Sopenharmony_ci } 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci inl->dif_app_bitmask_check = 5748c2ecf20Sopenharmony_ci cpu_to_be16(domain->sig.dif.apptag_check_mask); 5758c2ecf20Sopenharmony_ci} 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_cistatic int mlx5_set_bsf(struct ib_mr *sig_mr, 5788c2ecf20Sopenharmony_ci struct ib_sig_attrs *sig_attrs, 5798c2ecf20Sopenharmony_ci struct mlx5_bsf *bsf, u32 data_size) 5808c2ecf20Sopenharmony_ci{ 5818c2ecf20Sopenharmony_ci struct mlx5_core_sig_ctx *msig = to_mmr(sig_mr)->sig; 5828c2ecf20Sopenharmony_ci struct mlx5_bsf_basic *basic = &bsf->basic; 5838c2ecf20Sopenharmony_ci struct ib_sig_domain *mem = &sig_attrs->mem; 5848c2ecf20Sopenharmony_ci struct ib_sig_domain *wire = &sig_attrs->wire; 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci memset(bsf, 0, sizeof(*bsf)); 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci /* Basic + Extended + Inline */ 5898c2ecf20Sopenharmony_ci basic->bsf_size_sbs = 1 << 7; 5908c2ecf20Sopenharmony_ci /* Input domain check byte mask */ 5918c2ecf20Sopenharmony_ci basic->check_byte_mask = sig_attrs->check_mask; 5928c2ecf20Sopenharmony_ci basic->raw_data_size = cpu_to_be32(data_size); 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci /* Memory domain */ 5958c2ecf20Sopenharmony_ci switch (sig_attrs->mem.sig_type) { 5968c2ecf20Sopenharmony_ci case IB_SIG_TYPE_NONE: 5978c2ecf20Sopenharmony_ci break; 5988c2ecf20Sopenharmony_ci case IB_SIG_TYPE_T10_DIF: 5998c2ecf20Sopenharmony_ci basic->mem.bs_selector = bs_selector(mem->sig.dif.pi_interval); 6008c2ecf20Sopenharmony_ci basic->m_bfs_psv = cpu_to_be32(msig->psv_memory.psv_idx); 6018c2ecf20Sopenharmony_ci mlx5_fill_inl_bsf(mem, &bsf->m_inl); 6028c2ecf20Sopenharmony_ci break; 6038c2ecf20Sopenharmony_ci default: 6048c2ecf20Sopenharmony_ci return -EINVAL; 6058c2ecf20Sopenharmony_ci } 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci /* Wire domain */ 6088c2ecf20Sopenharmony_ci switch (sig_attrs->wire.sig_type) { 6098c2ecf20Sopenharmony_ci case IB_SIG_TYPE_NONE: 6108c2ecf20Sopenharmony_ci break; 6118c2ecf20Sopenharmony_ci case IB_SIG_TYPE_T10_DIF: 6128c2ecf20Sopenharmony_ci if (mem->sig.dif.pi_interval == wire->sig.dif.pi_interval && 6138c2ecf20Sopenharmony_ci mem->sig_type == wire->sig_type) { 6148c2ecf20Sopenharmony_ci /* Same block structure */ 6158c2ecf20Sopenharmony_ci basic->bsf_size_sbs |= 1 << 4; 6168c2ecf20Sopenharmony_ci if (mem->sig.dif.bg_type == wire->sig.dif.bg_type) 6178c2ecf20Sopenharmony_ci basic->wire.copy_byte_mask |= MLX5_CPY_GRD_MASK; 6188c2ecf20Sopenharmony_ci if (mem->sig.dif.app_tag == wire->sig.dif.app_tag) 6198c2ecf20Sopenharmony_ci basic->wire.copy_byte_mask |= MLX5_CPY_APP_MASK; 6208c2ecf20Sopenharmony_ci if (mem->sig.dif.ref_tag == wire->sig.dif.ref_tag) 6218c2ecf20Sopenharmony_ci basic->wire.copy_byte_mask |= MLX5_CPY_REF_MASK; 6228c2ecf20Sopenharmony_ci } else 6238c2ecf20Sopenharmony_ci basic->wire.bs_selector = 6248c2ecf20Sopenharmony_ci bs_selector(wire->sig.dif.pi_interval); 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci basic->w_bfs_psv = cpu_to_be32(msig->psv_wire.psv_idx); 6278c2ecf20Sopenharmony_ci mlx5_fill_inl_bsf(wire, &bsf->w_inl); 6288c2ecf20Sopenharmony_ci break; 6298c2ecf20Sopenharmony_ci default: 6308c2ecf20Sopenharmony_ci return -EINVAL; 6318c2ecf20Sopenharmony_ci } 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci return 0; 6348c2ecf20Sopenharmony_ci} 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_cistatic int set_sig_data_segment(const struct ib_send_wr *send_wr, 6388c2ecf20Sopenharmony_ci struct ib_mr *sig_mr, 6398c2ecf20Sopenharmony_ci struct ib_sig_attrs *sig_attrs, 6408c2ecf20Sopenharmony_ci struct mlx5_ib_qp *qp, void **seg, int *size, 6418c2ecf20Sopenharmony_ci void **cur_edge) 6428c2ecf20Sopenharmony_ci{ 6438c2ecf20Sopenharmony_ci struct mlx5_bsf *bsf; 6448c2ecf20Sopenharmony_ci u32 data_len; 6458c2ecf20Sopenharmony_ci u32 data_key; 6468c2ecf20Sopenharmony_ci u64 data_va; 6478c2ecf20Sopenharmony_ci u32 prot_len = 0; 6488c2ecf20Sopenharmony_ci u32 prot_key = 0; 6498c2ecf20Sopenharmony_ci u64 prot_va = 0; 6508c2ecf20Sopenharmony_ci bool prot = false; 6518c2ecf20Sopenharmony_ci int ret; 6528c2ecf20Sopenharmony_ci int wqe_size; 6538c2ecf20Sopenharmony_ci struct mlx5_ib_mr *mr = to_mmr(sig_mr); 6548c2ecf20Sopenharmony_ci struct mlx5_ib_mr *pi_mr = mr->pi_mr; 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci data_len = pi_mr->data_length; 6578c2ecf20Sopenharmony_ci data_key = pi_mr->ibmr.lkey; 6588c2ecf20Sopenharmony_ci data_va = pi_mr->data_iova; 6598c2ecf20Sopenharmony_ci if (pi_mr->meta_ndescs) { 6608c2ecf20Sopenharmony_ci prot_len = pi_mr->meta_length; 6618c2ecf20Sopenharmony_ci prot_key = pi_mr->ibmr.lkey; 6628c2ecf20Sopenharmony_ci prot_va = pi_mr->pi_iova; 6638c2ecf20Sopenharmony_ci prot = true; 6648c2ecf20Sopenharmony_ci } 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci if (!prot || (data_key == prot_key && data_va == prot_va && 6678c2ecf20Sopenharmony_ci data_len == prot_len)) { 6688c2ecf20Sopenharmony_ci /** 6698c2ecf20Sopenharmony_ci * Source domain doesn't contain signature information 6708c2ecf20Sopenharmony_ci * or data and protection are interleaved in memory. 6718c2ecf20Sopenharmony_ci * So need construct: 6728c2ecf20Sopenharmony_ci * ------------------ 6738c2ecf20Sopenharmony_ci * | data_klm | 6748c2ecf20Sopenharmony_ci * ------------------ 6758c2ecf20Sopenharmony_ci * | BSF | 6768c2ecf20Sopenharmony_ci * ------------------ 6778c2ecf20Sopenharmony_ci **/ 6788c2ecf20Sopenharmony_ci struct mlx5_klm *data_klm = *seg; 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_ci data_klm->bcount = cpu_to_be32(data_len); 6818c2ecf20Sopenharmony_ci data_klm->key = cpu_to_be32(data_key); 6828c2ecf20Sopenharmony_ci data_klm->va = cpu_to_be64(data_va); 6838c2ecf20Sopenharmony_ci wqe_size = ALIGN(sizeof(*data_klm), 64); 6848c2ecf20Sopenharmony_ci } else { 6858c2ecf20Sopenharmony_ci /** 6868c2ecf20Sopenharmony_ci * Source domain contains signature information 6878c2ecf20Sopenharmony_ci * So need construct a strided block format: 6888c2ecf20Sopenharmony_ci * --------------------------- 6898c2ecf20Sopenharmony_ci * | stride_block_ctrl | 6908c2ecf20Sopenharmony_ci * --------------------------- 6918c2ecf20Sopenharmony_ci * | data_klm | 6928c2ecf20Sopenharmony_ci * --------------------------- 6938c2ecf20Sopenharmony_ci * | prot_klm | 6948c2ecf20Sopenharmony_ci * --------------------------- 6958c2ecf20Sopenharmony_ci * | BSF | 6968c2ecf20Sopenharmony_ci * --------------------------- 6978c2ecf20Sopenharmony_ci **/ 6988c2ecf20Sopenharmony_ci struct mlx5_stride_block_ctrl_seg *sblock_ctrl; 6998c2ecf20Sopenharmony_ci struct mlx5_stride_block_entry *data_sentry; 7008c2ecf20Sopenharmony_ci struct mlx5_stride_block_entry *prot_sentry; 7018c2ecf20Sopenharmony_ci u16 block_size = sig_attrs->mem.sig.dif.pi_interval; 7028c2ecf20Sopenharmony_ci int prot_size; 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci sblock_ctrl = *seg; 7058c2ecf20Sopenharmony_ci data_sentry = (void *)sblock_ctrl + sizeof(*sblock_ctrl); 7068c2ecf20Sopenharmony_ci prot_sentry = (void *)data_sentry + sizeof(*data_sentry); 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci prot_size = prot_field_size(sig_attrs->mem.sig_type); 7098c2ecf20Sopenharmony_ci if (!prot_size) { 7108c2ecf20Sopenharmony_ci pr_err("Bad block size given: %u\n", block_size); 7118c2ecf20Sopenharmony_ci return -EINVAL; 7128c2ecf20Sopenharmony_ci } 7138c2ecf20Sopenharmony_ci sblock_ctrl->bcount_per_cycle = cpu_to_be32(block_size + 7148c2ecf20Sopenharmony_ci prot_size); 7158c2ecf20Sopenharmony_ci sblock_ctrl->op = cpu_to_be32(MLX5_STRIDE_BLOCK_OP); 7168c2ecf20Sopenharmony_ci sblock_ctrl->repeat_count = cpu_to_be32(data_len / block_size); 7178c2ecf20Sopenharmony_ci sblock_ctrl->num_entries = cpu_to_be16(2); 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci data_sentry->bcount = cpu_to_be16(block_size); 7208c2ecf20Sopenharmony_ci data_sentry->key = cpu_to_be32(data_key); 7218c2ecf20Sopenharmony_ci data_sentry->va = cpu_to_be64(data_va); 7228c2ecf20Sopenharmony_ci data_sentry->stride = cpu_to_be16(block_size); 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci prot_sentry->bcount = cpu_to_be16(prot_size); 7258c2ecf20Sopenharmony_ci prot_sentry->key = cpu_to_be32(prot_key); 7268c2ecf20Sopenharmony_ci prot_sentry->va = cpu_to_be64(prot_va); 7278c2ecf20Sopenharmony_ci prot_sentry->stride = cpu_to_be16(prot_size); 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci wqe_size = ALIGN(sizeof(*sblock_ctrl) + sizeof(*data_sentry) + 7308c2ecf20Sopenharmony_ci sizeof(*prot_sentry), 64); 7318c2ecf20Sopenharmony_ci } 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci *seg += wqe_size; 7348c2ecf20Sopenharmony_ci *size += wqe_size / 16; 7358c2ecf20Sopenharmony_ci handle_post_send_edge(&qp->sq, seg, *size, cur_edge); 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci bsf = *seg; 7388c2ecf20Sopenharmony_ci ret = mlx5_set_bsf(sig_mr, sig_attrs, bsf, data_len); 7398c2ecf20Sopenharmony_ci if (ret) 7408c2ecf20Sopenharmony_ci return -EINVAL; 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci *seg += sizeof(*bsf); 7438c2ecf20Sopenharmony_ci *size += sizeof(*bsf) / 16; 7448c2ecf20Sopenharmony_ci handle_post_send_edge(&qp->sq, seg, *size, cur_edge); 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci return 0; 7478c2ecf20Sopenharmony_ci} 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_cistatic void set_sig_mkey_segment(struct mlx5_mkey_seg *seg, 7508c2ecf20Sopenharmony_ci struct ib_mr *sig_mr, int access_flags, 7518c2ecf20Sopenharmony_ci u32 size, u32 length, u32 pdn) 7528c2ecf20Sopenharmony_ci{ 7538c2ecf20Sopenharmony_ci u32 sig_key = sig_mr->rkey; 7548c2ecf20Sopenharmony_ci u8 sigerr = to_mmr(sig_mr)->sig->sigerr_count & 1; 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci memset(seg, 0, sizeof(*seg)); 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci seg->flags = get_umr_flags(access_flags) | MLX5_MKC_ACCESS_MODE_KLMS; 7598c2ecf20Sopenharmony_ci seg->qpn_mkey7_0 = cpu_to_be32((sig_key & 0xff) | 0xffffff00); 7608c2ecf20Sopenharmony_ci seg->flags_pd = cpu_to_be32(MLX5_MKEY_REMOTE_INVAL | sigerr << 26 | 7618c2ecf20Sopenharmony_ci MLX5_MKEY_BSF_EN | pdn); 7628c2ecf20Sopenharmony_ci seg->len = cpu_to_be64(length); 7638c2ecf20Sopenharmony_ci seg->xlt_oct_size = cpu_to_be32(get_xlt_octo(size)); 7648c2ecf20Sopenharmony_ci seg->bsfs_octo_size = cpu_to_be32(MLX5_MKEY_BSF_OCTO_SIZE); 7658c2ecf20Sopenharmony_ci} 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_cistatic void set_sig_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr, 7688c2ecf20Sopenharmony_ci u32 size) 7698c2ecf20Sopenharmony_ci{ 7708c2ecf20Sopenharmony_ci memset(umr, 0, sizeof(*umr)); 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci umr->flags = MLX5_FLAGS_INLINE | MLX5_FLAGS_CHECK_FREE; 7738c2ecf20Sopenharmony_ci umr->xlt_octowords = cpu_to_be16(get_xlt_octo(size)); 7748c2ecf20Sopenharmony_ci umr->bsf_octowords = cpu_to_be16(MLX5_MKEY_BSF_OCTO_SIZE); 7758c2ecf20Sopenharmony_ci umr->mkey_mask = sig_mkey_mask(); 7768c2ecf20Sopenharmony_ci} 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_cistatic int set_pi_umr_wr(const struct ib_send_wr *send_wr, 7798c2ecf20Sopenharmony_ci struct mlx5_ib_qp *qp, void **seg, int *size, 7808c2ecf20Sopenharmony_ci void **cur_edge) 7818c2ecf20Sopenharmony_ci{ 7828c2ecf20Sopenharmony_ci const struct ib_reg_wr *wr = reg_wr(send_wr); 7838c2ecf20Sopenharmony_ci struct mlx5_ib_mr *sig_mr = to_mmr(wr->mr); 7848c2ecf20Sopenharmony_ci struct mlx5_ib_mr *pi_mr = sig_mr->pi_mr; 7858c2ecf20Sopenharmony_ci struct ib_sig_attrs *sig_attrs = sig_mr->ibmr.sig_attrs; 7868c2ecf20Sopenharmony_ci u32 pdn = to_mpd(qp->ibqp.pd)->pdn; 7878c2ecf20Sopenharmony_ci u32 xlt_size; 7888c2ecf20Sopenharmony_ci int region_len, ret; 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci if (unlikely(send_wr->num_sge != 0) || 7918c2ecf20Sopenharmony_ci unlikely(wr->access & IB_ACCESS_REMOTE_ATOMIC) || 7928c2ecf20Sopenharmony_ci unlikely(!sig_mr->sig) || unlikely(!qp->ibqp.integrity_en) || 7938c2ecf20Sopenharmony_ci unlikely(!sig_mr->sig->sig_status_checked)) 7948c2ecf20Sopenharmony_ci return -EINVAL; 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci /* length of the protected region, data + protection */ 7978c2ecf20Sopenharmony_ci region_len = pi_mr->ibmr.length; 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci /** 8008c2ecf20Sopenharmony_ci * KLM octoword size - if protection was provided 8018c2ecf20Sopenharmony_ci * then we use strided block format (3 octowords), 8028c2ecf20Sopenharmony_ci * else we use single KLM (1 octoword) 8038c2ecf20Sopenharmony_ci **/ 8048c2ecf20Sopenharmony_ci if (sig_attrs->mem.sig_type != IB_SIG_TYPE_NONE) 8058c2ecf20Sopenharmony_ci xlt_size = 0x30; 8068c2ecf20Sopenharmony_ci else 8078c2ecf20Sopenharmony_ci xlt_size = sizeof(struct mlx5_klm); 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci set_sig_umr_segment(*seg, xlt_size); 8108c2ecf20Sopenharmony_ci *seg += sizeof(struct mlx5_wqe_umr_ctrl_seg); 8118c2ecf20Sopenharmony_ci *size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16; 8128c2ecf20Sopenharmony_ci handle_post_send_edge(&qp->sq, seg, *size, cur_edge); 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci set_sig_mkey_segment(*seg, wr->mr, wr->access, xlt_size, region_len, 8158c2ecf20Sopenharmony_ci pdn); 8168c2ecf20Sopenharmony_ci *seg += sizeof(struct mlx5_mkey_seg); 8178c2ecf20Sopenharmony_ci *size += sizeof(struct mlx5_mkey_seg) / 16; 8188c2ecf20Sopenharmony_ci handle_post_send_edge(&qp->sq, seg, *size, cur_edge); 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci ret = set_sig_data_segment(send_wr, wr->mr, sig_attrs, qp, seg, size, 8218c2ecf20Sopenharmony_ci cur_edge); 8228c2ecf20Sopenharmony_ci if (ret) 8238c2ecf20Sopenharmony_ci return ret; 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci sig_mr->sig->sig_status_checked = false; 8268c2ecf20Sopenharmony_ci return 0; 8278c2ecf20Sopenharmony_ci} 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_cistatic int set_psv_wr(struct ib_sig_domain *domain, 8308c2ecf20Sopenharmony_ci u32 psv_idx, void **seg, int *size) 8318c2ecf20Sopenharmony_ci{ 8328c2ecf20Sopenharmony_ci struct mlx5_seg_set_psv *psv_seg = *seg; 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ci memset(psv_seg, 0, sizeof(*psv_seg)); 8358c2ecf20Sopenharmony_ci psv_seg->psv_num = cpu_to_be32(psv_idx); 8368c2ecf20Sopenharmony_ci switch (domain->sig_type) { 8378c2ecf20Sopenharmony_ci case IB_SIG_TYPE_NONE: 8388c2ecf20Sopenharmony_ci break; 8398c2ecf20Sopenharmony_ci case IB_SIG_TYPE_T10_DIF: 8408c2ecf20Sopenharmony_ci psv_seg->transient_sig = cpu_to_be32(domain->sig.dif.bg << 16 | 8418c2ecf20Sopenharmony_ci domain->sig.dif.app_tag); 8428c2ecf20Sopenharmony_ci psv_seg->ref_tag = cpu_to_be32(domain->sig.dif.ref_tag); 8438c2ecf20Sopenharmony_ci break; 8448c2ecf20Sopenharmony_ci default: 8458c2ecf20Sopenharmony_ci pr_err("Bad signature type (%d) is given.\n", 8468c2ecf20Sopenharmony_ci domain->sig_type); 8478c2ecf20Sopenharmony_ci return -EINVAL; 8488c2ecf20Sopenharmony_ci } 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci *seg += sizeof(*psv_seg); 8518c2ecf20Sopenharmony_ci *size += sizeof(*psv_seg) / 16; 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci return 0; 8548c2ecf20Sopenharmony_ci} 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_cistatic int set_reg_wr(struct mlx5_ib_qp *qp, 8578c2ecf20Sopenharmony_ci const struct ib_reg_wr *wr, 8588c2ecf20Sopenharmony_ci void **seg, int *size, void **cur_edge, 8598c2ecf20Sopenharmony_ci bool check_not_free) 8608c2ecf20Sopenharmony_ci{ 8618c2ecf20Sopenharmony_ci struct mlx5_ib_mr *mr = to_mmr(wr->mr); 8628c2ecf20Sopenharmony_ci struct mlx5_ib_pd *pd = to_mpd(qp->ibqp.pd); 8638c2ecf20Sopenharmony_ci struct mlx5_ib_dev *dev = to_mdev(pd->ibpd.device); 8648c2ecf20Sopenharmony_ci int mr_list_size = (mr->ndescs + mr->meta_ndescs) * mr->desc_size; 8658c2ecf20Sopenharmony_ci bool umr_inline = mr_list_size <= MLX5_IB_SQ_UMR_INLINE_THRESHOLD; 8668c2ecf20Sopenharmony_ci bool atomic = wr->access & IB_ACCESS_REMOTE_ATOMIC; 8678c2ecf20Sopenharmony_ci u8 flags = 0; 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci /* Matches access in mlx5_set_umr_free_mkey() */ 8708c2ecf20Sopenharmony_ci if (!mlx5_ib_can_reconfig_with_umr(dev, 0, wr->access)) { 8718c2ecf20Sopenharmony_ci mlx5_ib_warn( 8728c2ecf20Sopenharmony_ci to_mdev(qp->ibqp.device), 8738c2ecf20Sopenharmony_ci "Fast update for MR access flags is not possible\n"); 8748c2ecf20Sopenharmony_ci return -EINVAL; 8758c2ecf20Sopenharmony_ci } 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci if (unlikely(wr->wr.send_flags & IB_SEND_INLINE)) { 8788c2ecf20Sopenharmony_ci mlx5_ib_warn(to_mdev(qp->ibqp.device), 8798c2ecf20Sopenharmony_ci "Invalid IB_SEND_INLINE send flag\n"); 8808c2ecf20Sopenharmony_ci return -EINVAL; 8818c2ecf20Sopenharmony_ci } 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci if (check_not_free) 8848c2ecf20Sopenharmony_ci flags |= MLX5_UMR_CHECK_NOT_FREE; 8858c2ecf20Sopenharmony_ci if (umr_inline) 8868c2ecf20Sopenharmony_ci flags |= MLX5_UMR_INLINE; 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci set_reg_umr_seg(*seg, mr, flags, atomic); 8898c2ecf20Sopenharmony_ci *seg += sizeof(struct mlx5_wqe_umr_ctrl_seg); 8908c2ecf20Sopenharmony_ci *size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16; 8918c2ecf20Sopenharmony_ci handle_post_send_edge(&qp->sq, seg, *size, cur_edge); 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci set_reg_mkey_seg(*seg, mr, wr->key, wr->access); 8948c2ecf20Sopenharmony_ci *seg += sizeof(struct mlx5_mkey_seg); 8958c2ecf20Sopenharmony_ci *size += sizeof(struct mlx5_mkey_seg) / 16; 8968c2ecf20Sopenharmony_ci handle_post_send_edge(&qp->sq, seg, *size, cur_edge); 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci if (umr_inline) { 8998c2ecf20Sopenharmony_ci memcpy_send_wqe(&qp->sq, cur_edge, seg, size, mr->descs, 9008c2ecf20Sopenharmony_ci mr_list_size); 9018c2ecf20Sopenharmony_ci *size = ALIGN(*size, MLX5_SEND_WQE_BB >> 4); 9028c2ecf20Sopenharmony_ci } else { 9038c2ecf20Sopenharmony_ci set_reg_data_seg(*seg, mr, pd); 9048c2ecf20Sopenharmony_ci *seg += sizeof(struct mlx5_wqe_data_seg); 9058c2ecf20Sopenharmony_ci *size += (sizeof(struct mlx5_wqe_data_seg) / 16); 9068c2ecf20Sopenharmony_ci } 9078c2ecf20Sopenharmony_ci return 0; 9088c2ecf20Sopenharmony_ci} 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_cistatic void set_linv_wr(struct mlx5_ib_qp *qp, void **seg, int *size, 9118c2ecf20Sopenharmony_ci void **cur_edge) 9128c2ecf20Sopenharmony_ci{ 9138c2ecf20Sopenharmony_ci set_linv_umr_seg(*seg); 9148c2ecf20Sopenharmony_ci *seg += sizeof(struct mlx5_wqe_umr_ctrl_seg); 9158c2ecf20Sopenharmony_ci *size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16; 9168c2ecf20Sopenharmony_ci handle_post_send_edge(&qp->sq, seg, *size, cur_edge); 9178c2ecf20Sopenharmony_ci set_linv_mkey_seg(*seg); 9188c2ecf20Sopenharmony_ci *seg += sizeof(struct mlx5_mkey_seg); 9198c2ecf20Sopenharmony_ci *size += sizeof(struct mlx5_mkey_seg) / 16; 9208c2ecf20Sopenharmony_ci handle_post_send_edge(&qp->sq, seg, *size, cur_edge); 9218c2ecf20Sopenharmony_ci} 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_cistatic void dump_wqe(struct mlx5_ib_qp *qp, u32 idx, int size_16) 9248c2ecf20Sopenharmony_ci{ 9258c2ecf20Sopenharmony_ci __be32 *p = NULL; 9268c2ecf20Sopenharmony_ci int i, j; 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci pr_debug("dump WQE index %u:\n", idx); 9298c2ecf20Sopenharmony_ci for (i = 0, j = 0; i < size_16 * 4; i += 4, j += 4) { 9308c2ecf20Sopenharmony_ci if ((i & 0xf) == 0) { 9318c2ecf20Sopenharmony_ci p = mlx5_frag_buf_get_wqe(&qp->sq.fbc, idx); 9328c2ecf20Sopenharmony_ci pr_debug("WQBB at %p:\n", (void *)p); 9338c2ecf20Sopenharmony_ci j = 0; 9348c2ecf20Sopenharmony_ci idx = (idx + 1) & (qp->sq.wqe_cnt - 1); 9358c2ecf20Sopenharmony_ci } 9368c2ecf20Sopenharmony_ci pr_debug("%08x %08x %08x %08x\n", be32_to_cpu(p[j]), 9378c2ecf20Sopenharmony_ci be32_to_cpu(p[j + 1]), be32_to_cpu(p[j + 2]), 9388c2ecf20Sopenharmony_ci be32_to_cpu(p[j + 3])); 9398c2ecf20Sopenharmony_ci } 9408c2ecf20Sopenharmony_ci} 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_cistatic int __begin_wqe(struct mlx5_ib_qp *qp, void **seg, 9438c2ecf20Sopenharmony_ci struct mlx5_wqe_ctrl_seg **ctrl, 9448c2ecf20Sopenharmony_ci const struct ib_send_wr *wr, unsigned int *idx, 9458c2ecf20Sopenharmony_ci int *size, void **cur_edge, int nreq, 9468c2ecf20Sopenharmony_ci bool send_signaled, bool solicited) 9478c2ecf20Sopenharmony_ci{ 9488c2ecf20Sopenharmony_ci if (unlikely(mlx5_wq_overflow(&qp->sq, nreq, qp->ibqp.send_cq))) 9498c2ecf20Sopenharmony_ci return -ENOMEM; 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci *idx = qp->sq.cur_post & (qp->sq.wqe_cnt - 1); 9528c2ecf20Sopenharmony_ci *seg = mlx5_frag_buf_get_wqe(&qp->sq.fbc, *idx); 9538c2ecf20Sopenharmony_ci *ctrl = *seg; 9548c2ecf20Sopenharmony_ci *(uint32_t *)(*seg + 8) = 0; 9558c2ecf20Sopenharmony_ci (*ctrl)->imm = send_ieth(wr); 9568c2ecf20Sopenharmony_ci (*ctrl)->fm_ce_se = qp->sq_signal_bits | 9578c2ecf20Sopenharmony_ci (send_signaled ? MLX5_WQE_CTRL_CQ_UPDATE : 0) | 9588c2ecf20Sopenharmony_ci (solicited ? MLX5_WQE_CTRL_SOLICITED : 0); 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci *seg += sizeof(**ctrl); 9618c2ecf20Sopenharmony_ci *size = sizeof(**ctrl) / 16; 9628c2ecf20Sopenharmony_ci *cur_edge = qp->sq.cur_edge; 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci return 0; 9658c2ecf20Sopenharmony_ci} 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_cistatic int begin_wqe(struct mlx5_ib_qp *qp, void **seg, 9688c2ecf20Sopenharmony_ci struct mlx5_wqe_ctrl_seg **ctrl, 9698c2ecf20Sopenharmony_ci const struct ib_send_wr *wr, unsigned int *idx, int *size, 9708c2ecf20Sopenharmony_ci void **cur_edge, int nreq) 9718c2ecf20Sopenharmony_ci{ 9728c2ecf20Sopenharmony_ci return __begin_wqe(qp, seg, ctrl, wr, idx, size, cur_edge, nreq, 9738c2ecf20Sopenharmony_ci wr->send_flags & IB_SEND_SIGNALED, 9748c2ecf20Sopenharmony_ci wr->send_flags & IB_SEND_SOLICITED); 9758c2ecf20Sopenharmony_ci} 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_cistatic void finish_wqe(struct mlx5_ib_qp *qp, 9788c2ecf20Sopenharmony_ci struct mlx5_wqe_ctrl_seg *ctrl, 9798c2ecf20Sopenharmony_ci void *seg, u8 size, void *cur_edge, 9808c2ecf20Sopenharmony_ci unsigned int idx, u64 wr_id, int nreq, u8 fence, 9818c2ecf20Sopenharmony_ci u32 mlx5_opcode) 9828c2ecf20Sopenharmony_ci{ 9838c2ecf20Sopenharmony_ci u8 opmod = 0; 9848c2ecf20Sopenharmony_ci 9858c2ecf20Sopenharmony_ci ctrl->opmod_idx_opcode = cpu_to_be32(((u32)(qp->sq.cur_post) << 8) | 9868c2ecf20Sopenharmony_ci mlx5_opcode | ((u32)opmod << 24)); 9878c2ecf20Sopenharmony_ci ctrl->qpn_ds = cpu_to_be32(size | (qp->trans_qp.base.mqp.qpn << 8)); 9888c2ecf20Sopenharmony_ci ctrl->fm_ce_se |= fence; 9898c2ecf20Sopenharmony_ci if (unlikely(qp->flags_en & MLX5_QP_FLAG_SIGNATURE)) 9908c2ecf20Sopenharmony_ci ctrl->signature = wq_sig(ctrl); 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci qp->sq.wrid[idx] = wr_id; 9938c2ecf20Sopenharmony_ci qp->sq.w_list[idx].opcode = mlx5_opcode; 9948c2ecf20Sopenharmony_ci qp->sq.wqe_head[idx] = qp->sq.head + nreq; 9958c2ecf20Sopenharmony_ci qp->sq.cur_post += DIV_ROUND_UP(size * 16, MLX5_SEND_WQE_BB); 9968c2ecf20Sopenharmony_ci qp->sq.w_list[idx].next = qp->sq.cur_post; 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci /* We save the edge which was possibly updated during the WQE 9998c2ecf20Sopenharmony_ci * construction, into SQ's cache. 10008c2ecf20Sopenharmony_ci */ 10018c2ecf20Sopenharmony_ci seg = PTR_ALIGN(seg, MLX5_SEND_WQE_BB); 10028c2ecf20Sopenharmony_ci qp->sq.cur_edge = (unlikely(seg == cur_edge)) ? 10038c2ecf20Sopenharmony_ci get_sq_edge(&qp->sq, qp->sq.cur_post & 10048c2ecf20Sopenharmony_ci (qp->sq.wqe_cnt - 1)) : 10058c2ecf20Sopenharmony_ci cur_edge; 10068c2ecf20Sopenharmony_ci} 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_cistatic void handle_rdma_op(const struct ib_send_wr *wr, void **seg, int *size) 10098c2ecf20Sopenharmony_ci{ 10108c2ecf20Sopenharmony_ci set_raddr_seg(*seg, rdma_wr(wr)->remote_addr, rdma_wr(wr)->rkey); 10118c2ecf20Sopenharmony_ci *seg += sizeof(struct mlx5_wqe_raddr_seg); 10128c2ecf20Sopenharmony_ci *size += sizeof(struct mlx5_wqe_raddr_seg) / 16; 10138c2ecf20Sopenharmony_ci} 10148c2ecf20Sopenharmony_ci 10158c2ecf20Sopenharmony_cistatic void handle_local_inv(struct mlx5_ib_qp *qp, const struct ib_send_wr *wr, 10168c2ecf20Sopenharmony_ci struct mlx5_wqe_ctrl_seg **ctrl, void **seg, 10178c2ecf20Sopenharmony_ci int *size, void **cur_edge, unsigned int idx) 10188c2ecf20Sopenharmony_ci{ 10198c2ecf20Sopenharmony_ci qp->sq.wr_data[idx] = IB_WR_LOCAL_INV; 10208c2ecf20Sopenharmony_ci (*ctrl)->imm = cpu_to_be32(wr->ex.invalidate_rkey); 10218c2ecf20Sopenharmony_ci set_linv_wr(qp, seg, size, cur_edge); 10228c2ecf20Sopenharmony_ci} 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_cistatic int handle_reg_mr(struct mlx5_ib_qp *qp, const struct ib_send_wr *wr, 10258c2ecf20Sopenharmony_ci struct mlx5_wqe_ctrl_seg **ctrl, void **seg, int *size, 10268c2ecf20Sopenharmony_ci void **cur_edge, unsigned int idx) 10278c2ecf20Sopenharmony_ci{ 10288c2ecf20Sopenharmony_ci qp->sq.wr_data[idx] = IB_WR_REG_MR; 10298c2ecf20Sopenharmony_ci (*ctrl)->imm = cpu_to_be32(reg_wr(wr)->key); 10308c2ecf20Sopenharmony_ci return set_reg_wr(qp, reg_wr(wr), seg, size, cur_edge, true); 10318c2ecf20Sopenharmony_ci} 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_cistatic int handle_psv(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp, 10348c2ecf20Sopenharmony_ci const struct ib_send_wr *wr, 10358c2ecf20Sopenharmony_ci struct mlx5_wqe_ctrl_seg **ctrl, void **seg, int *size, 10368c2ecf20Sopenharmony_ci void **cur_edge, unsigned int *idx, int nreq, 10378c2ecf20Sopenharmony_ci struct ib_sig_domain *domain, u32 psv_index, 10388c2ecf20Sopenharmony_ci u8 next_fence) 10398c2ecf20Sopenharmony_ci{ 10408c2ecf20Sopenharmony_ci int err; 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci /* 10438c2ecf20Sopenharmony_ci * SET_PSV WQEs are not signaled and solicited on error. 10448c2ecf20Sopenharmony_ci */ 10458c2ecf20Sopenharmony_ci err = __begin_wqe(qp, seg, ctrl, wr, idx, size, cur_edge, nreq, 10468c2ecf20Sopenharmony_ci false, true); 10478c2ecf20Sopenharmony_ci if (unlikely(err)) { 10488c2ecf20Sopenharmony_ci mlx5_ib_warn(dev, "\n"); 10498c2ecf20Sopenharmony_ci err = -ENOMEM; 10508c2ecf20Sopenharmony_ci goto out; 10518c2ecf20Sopenharmony_ci } 10528c2ecf20Sopenharmony_ci err = set_psv_wr(domain, psv_index, seg, size); 10538c2ecf20Sopenharmony_ci if (unlikely(err)) { 10548c2ecf20Sopenharmony_ci mlx5_ib_warn(dev, "\n"); 10558c2ecf20Sopenharmony_ci goto out; 10568c2ecf20Sopenharmony_ci } 10578c2ecf20Sopenharmony_ci finish_wqe(qp, *ctrl, *seg, *size, *cur_edge, *idx, wr->wr_id, nreq, 10588c2ecf20Sopenharmony_ci next_fence, MLX5_OPCODE_SET_PSV); 10598c2ecf20Sopenharmony_ci 10608c2ecf20Sopenharmony_ciout: 10618c2ecf20Sopenharmony_ci return err; 10628c2ecf20Sopenharmony_ci} 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_cistatic int handle_reg_mr_integrity(struct mlx5_ib_dev *dev, 10658c2ecf20Sopenharmony_ci struct mlx5_ib_qp *qp, 10668c2ecf20Sopenharmony_ci const struct ib_send_wr *wr, 10678c2ecf20Sopenharmony_ci struct mlx5_wqe_ctrl_seg **ctrl, void **seg, 10688c2ecf20Sopenharmony_ci int *size, void **cur_edge, 10698c2ecf20Sopenharmony_ci unsigned int *idx, int nreq, u8 fence, 10708c2ecf20Sopenharmony_ci u8 next_fence) 10718c2ecf20Sopenharmony_ci{ 10728c2ecf20Sopenharmony_ci struct mlx5_ib_mr *mr; 10738c2ecf20Sopenharmony_ci struct mlx5_ib_mr *pi_mr; 10748c2ecf20Sopenharmony_ci struct mlx5_ib_mr pa_pi_mr; 10758c2ecf20Sopenharmony_ci struct ib_sig_attrs *sig_attrs; 10768c2ecf20Sopenharmony_ci struct ib_reg_wr reg_pi_wr; 10778c2ecf20Sopenharmony_ci int err; 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci qp->sq.wr_data[*idx] = IB_WR_REG_MR_INTEGRITY; 10808c2ecf20Sopenharmony_ci 10818c2ecf20Sopenharmony_ci mr = to_mmr(reg_wr(wr)->mr); 10828c2ecf20Sopenharmony_ci pi_mr = mr->pi_mr; 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_ci if (pi_mr) { 10858c2ecf20Sopenharmony_ci memset(®_pi_wr, 0, 10868c2ecf20Sopenharmony_ci sizeof(struct ib_reg_wr)); 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_ci reg_pi_wr.mr = &pi_mr->ibmr; 10898c2ecf20Sopenharmony_ci reg_pi_wr.access = reg_wr(wr)->access; 10908c2ecf20Sopenharmony_ci reg_pi_wr.key = pi_mr->ibmr.rkey; 10918c2ecf20Sopenharmony_ci 10928c2ecf20Sopenharmony_ci (*ctrl)->imm = cpu_to_be32(reg_pi_wr.key); 10938c2ecf20Sopenharmony_ci /* UMR for data + prot registration */ 10948c2ecf20Sopenharmony_ci err = set_reg_wr(qp, ®_pi_wr, seg, size, cur_edge, false); 10958c2ecf20Sopenharmony_ci if (unlikely(err)) 10968c2ecf20Sopenharmony_ci goto out; 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci finish_wqe(qp, *ctrl, *seg, *size, *cur_edge, *idx, wr->wr_id, 10998c2ecf20Sopenharmony_ci nreq, fence, MLX5_OPCODE_UMR); 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci err = begin_wqe(qp, seg, ctrl, wr, idx, size, cur_edge, nreq); 11028c2ecf20Sopenharmony_ci if (unlikely(err)) { 11038c2ecf20Sopenharmony_ci mlx5_ib_warn(dev, "\n"); 11048c2ecf20Sopenharmony_ci err = -ENOMEM; 11058c2ecf20Sopenharmony_ci goto out; 11068c2ecf20Sopenharmony_ci } 11078c2ecf20Sopenharmony_ci } else { 11088c2ecf20Sopenharmony_ci memset(&pa_pi_mr, 0, sizeof(struct mlx5_ib_mr)); 11098c2ecf20Sopenharmony_ci /* No UMR, use local_dma_lkey */ 11108c2ecf20Sopenharmony_ci pa_pi_mr.ibmr.lkey = mr->ibmr.pd->local_dma_lkey; 11118c2ecf20Sopenharmony_ci pa_pi_mr.ndescs = mr->ndescs; 11128c2ecf20Sopenharmony_ci pa_pi_mr.data_length = mr->data_length; 11138c2ecf20Sopenharmony_ci pa_pi_mr.data_iova = mr->data_iova; 11148c2ecf20Sopenharmony_ci if (mr->meta_ndescs) { 11158c2ecf20Sopenharmony_ci pa_pi_mr.meta_ndescs = mr->meta_ndescs; 11168c2ecf20Sopenharmony_ci pa_pi_mr.meta_length = mr->meta_length; 11178c2ecf20Sopenharmony_ci pa_pi_mr.pi_iova = mr->pi_iova; 11188c2ecf20Sopenharmony_ci } 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci pa_pi_mr.ibmr.length = mr->ibmr.length; 11218c2ecf20Sopenharmony_ci mr->pi_mr = &pa_pi_mr; 11228c2ecf20Sopenharmony_ci } 11238c2ecf20Sopenharmony_ci (*ctrl)->imm = cpu_to_be32(mr->ibmr.rkey); 11248c2ecf20Sopenharmony_ci /* UMR for sig MR */ 11258c2ecf20Sopenharmony_ci err = set_pi_umr_wr(wr, qp, seg, size, cur_edge); 11268c2ecf20Sopenharmony_ci if (unlikely(err)) { 11278c2ecf20Sopenharmony_ci mlx5_ib_warn(dev, "\n"); 11288c2ecf20Sopenharmony_ci goto out; 11298c2ecf20Sopenharmony_ci } 11308c2ecf20Sopenharmony_ci finish_wqe(qp, *ctrl, *seg, *size, *cur_edge, *idx, wr->wr_id, nreq, 11318c2ecf20Sopenharmony_ci fence, MLX5_OPCODE_UMR); 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci sig_attrs = mr->ibmr.sig_attrs; 11348c2ecf20Sopenharmony_ci err = handle_psv(dev, qp, wr, ctrl, seg, size, cur_edge, idx, nreq, 11358c2ecf20Sopenharmony_ci &sig_attrs->mem, mr->sig->psv_memory.psv_idx, 11368c2ecf20Sopenharmony_ci next_fence); 11378c2ecf20Sopenharmony_ci if (unlikely(err)) 11388c2ecf20Sopenharmony_ci goto out; 11398c2ecf20Sopenharmony_ci 11408c2ecf20Sopenharmony_ci err = handle_psv(dev, qp, wr, ctrl, seg, size, cur_edge, idx, nreq, 11418c2ecf20Sopenharmony_ci &sig_attrs->wire, mr->sig->psv_wire.psv_idx, 11428c2ecf20Sopenharmony_ci next_fence); 11438c2ecf20Sopenharmony_ci if (unlikely(err)) 11448c2ecf20Sopenharmony_ci goto out; 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci qp->next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL; 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ciout: 11498c2ecf20Sopenharmony_ci return err; 11508c2ecf20Sopenharmony_ci} 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_cistatic int handle_qpt_rc(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp, 11538c2ecf20Sopenharmony_ci const struct ib_send_wr *wr, 11548c2ecf20Sopenharmony_ci struct mlx5_wqe_ctrl_seg **ctrl, void **seg, int *size, 11558c2ecf20Sopenharmony_ci void **cur_edge, unsigned int *idx, int nreq, u8 fence, 11568c2ecf20Sopenharmony_ci u8 next_fence, int *num_sge) 11578c2ecf20Sopenharmony_ci{ 11588c2ecf20Sopenharmony_ci int err = 0; 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ci switch (wr->opcode) { 11618c2ecf20Sopenharmony_ci case IB_WR_RDMA_READ: 11628c2ecf20Sopenharmony_ci case IB_WR_RDMA_WRITE: 11638c2ecf20Sopenharmony_ci case IB_WR_RDMA_WRITE_WITH_IMM: 11648c2ecf20Sopenharmony_ci handle_rdma_op(wr, seg, size); 11658c2ecf20Sopenharmony_ci break; 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci case IB_WR_ATOMIC_CMP_AND_SWP: 11688c2ecf20Sopenharmony_ci case IB_WR_ATOMIC_FETCH_AND_ADD: 11698c2ecf20Sopenharmony_ci case IB_WR_MASKED_ATOMIC_CMP_AND_SWP: 11708c2ecf20Sopenharmony_ci mlx5_ib_warn(dev, "Atomic operations are not supported yet\n"); 11718c2ecf20Sopenharmony_ci err = -EOPNOTSUPP; 11728c2ecf20Sopenharmony_ci goto out; 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_ci case IB_WR_LOCAL_INV: 11758c2ecf20Sopenharmony_ci handle_local_inv(qp, wr, ctrl, seg, size, cur_edge, *idx); 11768c2ecf20Sopenharmony_ci *num_sge = 0; 11778c2ecf20Sopenharmony_ci break; 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci case IB_WR_REG_MR: 11808c2ecf20Sopenharmony_ci err = handle_reg_mr(qp, wr, ctrl, seg, size, cur_edge, *idx); 11818c2ecf20Sopenharmony_ci if (unlikely(err)) 11828c2ecf20Sopenharmony_ci goto out; 11838c2ecf20Sopenharmony_ci *num_sge = 0; 11848c2ecf20Sopenharmony_ci break; 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci case IB_WR_REG_MR_INTEGRITY: 11878c2ecf20Sopenharmony_ci err = handle_reg_mr_integrity(dev, qp, wr, ctrl, seg, size, 11888c2ecf20Sopenharmony_ci cur_edge, idx, nreq, fence, 11898c2ecf20Sopenharmony_ci next_fence); 11908c2ecf20Sopenharmony_ci if (unlikely(err)) 11918c2ecf20Sopenharmony_ci goto out; 11928c2ecf20Sopenharmony_ci *num_sge = 0; 11938c2ecf20Sopenharmony_ci break; 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci default: 11968c2ecf20Sopenharmony_ci break; 11978c2ecf20Sopenharmony_ci } 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ciout: 12008c2ecf20Sopenharmony_ci return err; 12018c2ecf20Sopenharmony_ci} 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_cistatic void handle_qpt_uc(const struct ib_send_wr *wr, void **seg, int *size) 12048c2ecf20Sopenharmony_ci{ 12058c2ecf20Sopenharmony_ci switch (wr->opcode) { 12068c2ecf20Sopenharmony_ci case IB_WR_RDMA_WRITE: 12078c2ecf20Sopenharmony_ci case IB_WR_RDMA_WRITE_WITH_IMM: 12088c2ecf20Sopenharmony_ci handle_rdma_op(wr, seg, size); 12098c2ecf20Sopenharmony_ci break; 12108c2ecf20Sopenharmony_ci default: 12118c2ecf20Sopenharmony_ci break; 12128c2ecf20Sopenharmony_ci } 12138c2ecf20Sopenharmony_ci} 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_cistatic void handle_qpt_hw_gsi(struct mlx5_ib_qp *qp, 12168c2ecf20Sopenharmony_ci const struct ib_send_wr *wr, void **seg, 12178c2ecf20Sopenharmony_ci int *size, void **cur_edge) 12188c2ecf20Sopenharmony_ci{ 12198c2ecf20Sopenharmony_ci set_datagram_seg(*seg, wr); 12208c2ecf20Sopenharmony_ci *seg += sizeof(struct mlx5_wqe_datagram_seg); 12218c2ecf20Sopenharmony_ci *size += sizeof(struct mlx5_wqe_datagram_seg) / 16; 12228c2ecf20Sopenharmony_ci handle_post_send_edge(&qp->sq, seg, *size, cur_edge); 12238c2ecf20Sopenharmony_ci} 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_cistatic void handle_qpt_ud(struct mlx5_ib_qp *qp, const struct ib_send_wr *wr, 12268c2ecf20Sopenharmony_ci void **seg, int *size, void **cur_edge) 12278c2ecf20Sopenharmony_ci{ 12288c2ecf20Sopenharmony_ci set_datagram_seg(*seg, wr); 12298c2ecf20Sopenharmony_ci *seg += sizeof(struct mlx5_wqe_datagram_seg); 12308c2ecf20Sopenharmony_ci *size += sizeof(struct mlx5_wqe_datagram_seg) / 16; 12318c2ecf20Sopenharmony_ci handle_post_send_edge(&qp->sq, seg, *size, cur_edge); 12328c2ecf20Sopenharmony_ci 12338c2ecf20Sopenharmony_ci /* handle qp that supports ud offload */ 12348c2ecf20Sopenharmony_ci if (qp->flags & IB_QP_CREATE_IPOIB_UD_LSO) { 12358c2ecf20Sopenharmony_ci struct mlx5_wqe_eth_pad *pad; 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci pad = *seg; 12388c2ecf20Sopenharmony_ci memset(pad, 0, sizeof(struct mlx5_wqe_eth_pad)); 12398c2ecf20Sopenharmony_ci *seg += sizeof(struct mlx5_wqe_eth_pad); 12408c2ecf20Sopenharmony_ci *size += sizeof(struct mlx5_wqe_eth_pad) / 16; 12418c2ecf20Sopenharmony_ci set_eth_seg(wr, qp, seg, size, cur_edge); 12428c2ecf20Sopenharmony_ci handle_post_send_edge(&qp->sq, seg, *size, cur_edge); 12438c2ecf20Sopenharmony_ci } 12448c2ecf20Sopenharmony_ci} 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_cistatic int handle_qpt_reg_umr(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp, 12478c2ecf20Sopenharmony_ci const struct ib_send_wr *wr, 12488c2ecf20Sopenharmony_ci struct mlx5_wqe_ctrl_seg **ctrl, void **seg, 12498c2ecf20Sopenharmony_ci int *size, void **cur_edge, unsigned int idx) 12508c2ecf20Sopenharmony_ci{ 12518c2ecf20Sopenharmony_ci int err = 0; 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci if (unlikely(wr->opcode != MLX5_IB_WR_UMR)) { 12548c2ecf20Sopenharmony_ci err = -EINVAL; 12558c2ecf20Sopenharmony_ci mlx5_ib_warn(dev, "bad opcode %d\n", wr->opcode); 12568c2ecf20Sopenharmony_ci goto out; 12578c2ecf20Sopenharmony_ci } 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci qp->sq.wr_data[idx] = MLX5_IB_WR_UMR; 12608c2ecf20Sopenharmony_ci (*ctrl)->imm = cpu_to_be32(umr_wr(wr)->mkey); 12618c2ecf20Sopenharmony_ci err = set_reg_umr_segment(dev, *seg, wr); 12628c2ecf20Sopenharmony_ci if (unlikely(err)) 12638c2ecf20Sopenharmony_ci goto out; 12648c2ecf20Sopenharmony_ci *seg += sizeof(struct mlx5_wqe_umr_ctrl_seg); 12658c2ecf20Sopenharmony_ci *size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16; 12668c2ecf20Sopenharmony_ci handle_post_send_edge(&qp->sq, seg, *size, cur_edge); 12678c2ecf20Sopenharmony_ci set_reg_mkey_segment(dev, *seg, wr); 12688c2ecf20Sopenharmony_ci *seg += sizeof(struct mlx5_mkey_seg); 12698c2ecf20Sopenharmony_ci *size += sizeof(struct mlx5_mkey_seg) / 16; 12708c2ecf20Sopenharmony_ci handle_post_send_edge(&qp->sq, seg, *size, cur_edge); 12718c2ecf20Sopenharmony_ciout: 12728c2ecf20Sopenharmony_ci return err; 12738c2ecf20Sopenharmony_ci} 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_ciint mlx5_ib_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr, 12768c2ecf20Sopenharmony_ci const struct ib_send_wr **bad_wr, bool drain) 12778c2ecf20Sopenharmony_ci{ 12788c2ecf20Sopenharmony_ci struct mlx5_wqe_ctrl_seg *ctrl = NULL; /* compiler warning */ 12798c2ecf20Sopenharmony_ci struct mlx5_ib_dev *dev = to_mdev(ibqp->device); 12808c2ecf20Sopenharmony_ci struct mlx5_core_dev *mdev = dev->mdev; 12818c2ecf20Sopenharmony_ci struct mlx5_ib_qp *qp; 12828c2ecf20Sopenharmony_ci struct mlx5_wqe_xrc_seg *xrc; 12838c2ecf20Sopenharmony_ci struct mlx5_bf *bf; 12848c2ecf20Sopenharmony_ci void *cur_edge; 12858c2ecf20Sopenharmony_ci int size; 12868c2ecf20Sopenharmony_ci unsigned long flags; 12878c2ecf20Sopenharmony_ci unsigned int idx; 12888c2ecf20Sopenharmony_ci int err = 0; 12898c2ecf20Sopenharmony_ci int num_sge; 12908c2ecf20Sopenharmony_ci void *seg; 12918c2ecf20Sopenharmony_ci int nreq; 12928c2ecf20Sopenharmony_ci int i; 12938c2ecf20Sopenharmony_ci u8 next_fence = 0; 12948c2ecf20Sopenharmony_ci u8 fence; 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_ci if (unlikely(mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR && 12978c2ecf20Sopenharmony_ci !drain)) { 12988c2ecf20Sopenharmony_ci *bad_wr = wr; 12998c2ecf20Sopenharmony_ci return -EIO; 13008c2ecf20Sopenharmony_ci } 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci if (unlikely(ibqp->qp_type == IB_QPT_GSI)) 13038c2ecf20Sopenharmony_ci return mlx5_ib_gsi_post_send(ibqp, wr, bad_wr); 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_ci qp = to_mqp(ibqp); 13068c2ecf20Sopenharmony_ci bf = &qp->bf; 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci spin_lock_irqsave(&qp->sq.lock, flags); 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci for (nreq = 0; wr; nreq++, wr = wr->next) { 13118c2ecf20Sopenharmony_ci if (unlikely(wr->opcode >= ARRAY_SIZE(mlx5_ib_opcode))) { 13128c2ecf20Sopenharmony_ci mlx5_ib_warn(dev, "\n"); 13138c2ecf20Sopenharmony_ci err = -EINVAL; 13148c2ecf20Sopenharmony_ci *bad_wr = wr; 13158c2ecf20Sopenharmony_ci goto out; 13168c2ecf20Sopenharmony_ci } 13178c2ecf20Sopenharmony_ci 13188c2ecf20Sopenharmony_ci num_sge = wr->num_sge; 13198c2ecf20Sopenharmony_ci if (unlikely(num_sge > qp->sq.max_gs)) { 13208c2ecf20Sopenharmony_ci mlx5_ib_warn(dev, "\n"); 13218c2ecf20Sopenharmony_ci err = -EINVAL; 13228c2ecf20Sopenharmony_ci *bad_wr = wr; 13238c2ecf20Sopenharmony_ci goto out; 13248c2ecf20Sopenharmony_ci } 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_ci err = begin_wqe(qp, &seg, &ctrl, wr, &idx, &size, &cur_edge, 13278c2ecf20Sopenharmony_ci nreq); 13288c2ecf20Sopenharmony_ci if (err) { 13298c2ecf20Sopenharmony_ci mlx5_ib_warn(dev, "\n"); 13308c2ecf20Sopenharmony_ci err = -ENOMEM; 13318c2ecf20Sopenharmony_ci *bad_wr = wr; 13328c2ecf20Sopenharmony_ci goto out; 13338c2ecf20Sopenharmony_ci } 13348c2ecf20Sopenharmony_ci 13358c2ecf20Sopenharmony_ci if (wr->opcode == IB_WR_REG_MR || 13368c2ecf20Sopenharmony_ci wr->opcode == IB_WR_REG_MR_INTEGRITY) { 13378c2ecf20Sopenharmony_ci fence = dev->umr_fence; 13388c2ecf20Sopenharmony_ci next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL; 13398c2ecf20Sopenharmony_ci } else { 13408c2ecf20Sopenharmony_ci if (wr->send_flags & IB_SEND_FENCE) { 13418c2ecf20Sopenharmony_ci if (qp->next_fence) 13428c2ecf20Sopenharmony_ci fence = MLX5_FENCE_MODE_SMALL_AND_FENCE; 13438c2ecf20Sopenharmony_ci else 13448c2ecf20Sopenharmony_ci fence = MLX5_FENCE_MODE_FENCE; 13458c2ecf20Sopenharmony_ci } else { 13468c2ecf20Sopenharmony_ci fence = qp->next_fence; 13478c2ecf20Sopenharmony_ci } 13488c2ecf20Sopenharmony_ci } 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci switch (ibqp->qp_type) { 13518c2ecf20Sopenharmony_ci case IB_QPT_XRC_INI: 13528c2ecf20Sopenharmony_ci xrc = seg; 13538c2ecf20Sopenharmony_ci seg += sizeof(*xrc); 13548c2ecf20Sopenharmony_ci size += sizeof(*xrc) / 16; 13558c2ecf20Sopenharmony_ci fallthrough; 13568c2ecf20Sopenharmony_ci case IB_QPT_RC: 13578c2ecf20Sopenharmony_ci err = handle_qpt_rc(dev, qp, wr, &ctrl, &seg, &size, 13588c2ecf20Sopenharmony_ci &cur_edge, &idx, nreq, fence, 13598c2ecf20Sopenharmony_ci next_fence, &num_sge); 13608c2ecf20Sopenharmony_ci if (unlikely(err)) { 13618c2ecf20Sopenharmony_ci *bad_wr = wr; 13628c2ecf20Sopenharmony_ci goto out; 13638c2ecf20Sopenharmony_ci } else if (wr->opcode == IB_WR_REG_MR_INTEGRITY) { 13648c2ecf20Sopenharmony_ci goto skip_psv; 13658c2ecf20Sopenharmony_ci } 13668c2ecf20Sopenharmony_ci break; 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci case IB_QPT_UC: 13698c2ecf20Sopenharmony_ci handle_qpt_uc(wr, &seg, &size); 13708c2ecf20Sopenharmony_ci break; 13718c2ecf20Sopenharmony_ci case IB_QPT_SMI: 13728c2ecf20Sopenharmony_ci if (unlikely(!mdev->port_caps[qp->port - 1].has_smi)) { 13738c2ecf20Sopenharmony_ci mlx5_ib_warn(dev, "Send SMP MADs is not allowed\n"); 13748c2ecf20Sopenharmony_ci err = -EPERM; 13758c2ecf20Sopenharmony_ci *bad_wr = wr; 13768c2ecf20Sopenharmony_ci goto out; 13778c2ecf20Sopenharmony_ci } 13788c2ecf20Sopenharmony_ci fallthrough; 13798c2ecf20Sopenharmony_ci case MLX5_IB_QPT_HW_GSI: 13808c2ecf20Sopenharmony_ci handle_qpt_hw_gsi(qp, wr, &seg, &size, &cur_edge); 13818c2ecf20Sopenharmony_ci break; 13828c2ecf20Sopenharmony_ci case IB_QPT_UD: 13838c2ecf20Sopenharmony_ci handle_qpt_ud(qp, wr, &seg, &size, &cur_edge); 13848c2ecf20Sopenharmony_ci break; 13858c2ecf20Sopenharmony_ci case MLX5_IB_QPT_REG_UMR: 13868c2ecf20Sopenharmony_ci err = handle_qpt_reg_umr(dev, qp, wr, &ctrl, &seg, 13878c2ecf20Sopenharmony_ci &size, &cur_edge, idx); 13888c2ecf20Sopenharmony_ci if (unlikely(err)) 13898c2ecf20Sopenharmony_ci goto out; 13908c2ecf20Sopenharmony_ci break; 13918c2ecf20Sopenharmony_ci 13928c2ecf20Sopenharmony_ci default: 13938c2ecf20Sopenharmony_ci break; 13948c2ecf20Sopenharmony_ci } 13958c2ecf20Sopenharmony_ci 13968c2ecf20Sopenharmony_ci if (wr->send_flags & IB_SEND_INLINE && num_sge) { 13978c2ecf20Sopenharmony_ci err = set_data_inl_seg(qp, wr, &seg, &size, &cur_edge); 13988c2ecf20Sopenharmony_ci if (unlikely(err)) { 13998c2ecf20Sopenharmony_ci mlx5_ib_warn(dev, "\n"); 14008c2ecf20Sopenharmony_ci *bad_wr = wr; 14018c2ecf20Sopenharmony_ci goto out; 14028c2ecf20Sopenharmony_ci } 14038c2ecf20Sopenharmony_ci } else { 14048c2ecf20Sopenharmony_ci for (i = 0; i < num_sge; i++) { 14058c2ecf20Sopenharmony_ci handle_post_send_edge(&qp->sq, &seg, size, 14068c2ecf20Sopenharmony_ci &cur_edge); 14078c2ecf20Sopenharmony_ci if (unlikely(!wr->sg_list[i].length)) 14088c2ecf20Sopenharmony_ci continue; 14098c2ecf20Sopenharmony_ci 14108c2ecf20Sopenharmony_ci set_data_ptr_seg( 14118c2ecf20Sopenharmony_ci (struct mlx5_wqe_data_seg *)seg, 14128c2ecf20Sopenharmony_ci wr->sg_list + i); 14138c2ecf20Sopenharmony_ci size += sizeof(struct mlx5_wqe_data_seg) / 16; 14148c2ecf20Sopenharmony_ci seg += sizeof(struct mlx5_wqe_data_seg); 14158c2ecf20Sopenharmony_ci } 14168c2ecf20Sopenharmony_ci } 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_ci qp->next_fence = next_fence; 14198c2ecf20Sopenharmony_ci finish_wqe(qp, ctrl, seg, size, cur_edge, idx, wr->wr_id, nreq, 14208c2ecf20Sopenharmony_ci fence, mlx5_ib_opcode[wr->opcode]); 14218c2ecf20Sopenharmony_ciskip_psv: 14228c2ecf20Sopenharmony_ci if (0) 14238c2ecf20Sopenharmony_ci dump_wqe(qp, idx, size); 14248c2ecf20Sopenharmony_ci } 14258c2ecf20Sopenharmony_ci 14268c2ecf20Sopenharmony_ciout: 14278c2ecf20Sopenharmony_ci if (likely(nreq)) { 14288c2ecf20Sopenharmony_ci qp->sq.head += nreq; 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci /* Make sure that descriptors are written before 14318c2ecf20Sopenharmony_ci * updating doorbell record and ringing the doorbell 14328c2ecf20Sopenharmony_ci */ 14338c2ecf20Sopenharmony_ci wmb(); 14348c2ecf20Sopenharmony_ci 14358c2ecf20Sopenharmony_ci qp->db.db[MLX5_SND_DBR] = cpu_to_be32(qp->sq.cur_post); 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci /* Make sure doorbell record is visible to the HCA before 14388c2ecf20Sopenharmony_ci * we hit doorbell. 14398c2ecf20Sopenharmony_ci */ 14408c2ecf20Sopenharmony_ci wmb(); 14418c2ecf20Sopenharmony_ci 14428c2ecf20Sopenharmony_ci mlx5_write64((__be32 *)ctrl, bf->bfreg->map + bf->offset); 14438c2ecf20Sopenharmony_ci /* Make sure doorbells don't leak out of SQ spinlock 14448c2ecf20Sopenharmony_ci * and reach the HCA out of order. 14458c2ecf20Sopenharmony_ci */ 14468c2ecf20Sopenharmony_ci bf->offset ^= bf->buf_size; 14478c2ecf20Sopenharmony_ci } 14488c2ecf20Sopenharmony_ci 14498c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->sq.lock, flags); 14508c2ecf20Sopenharmony_ci 14518c2ecf20Sopenharmony_ci return err; 14528c2ecf20Sopenharmony_ci} 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_cistatic void set_sig_seg(struct mlx5_rwqe_sig *sig, int max_gs) 14558c2ecf20Sopenharmony_ci{ 14568c2ecf20Sopenharmony_ci sig->signature = calc_sig(sig, (max_gs + 1) << 2); 14578c2ecf20Sopenharmony_ci} 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_ciint mlx5_ib_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr, 14608c2ecf20Sopenharmony_ci const struct ib_recv_wr **bad_wr, bool drain) 14618c2ecf20Sopenharmony_ci{ 14628c2ecf20Sopenharmony_ci struct mlx5_ib_qp *qp = to_mqp(ibqp); 14638c2ecf20Sopenharmony_ci struct mlx5_wqe_data_seg *scat; 14648c2ecf20Sopenharmony_ci struct mlx5_rwqe_sig *sig; 14658c2ecf20Sopenharmony_ci struct mlx5_ib_dev *dev = to_mdev(ibqp->device); 14668c2ecf20Sopenharmony_ci struct mlx5_core_dev *mdev = dev->mdev; 14678c2ecf20Sopenharmony_ci unsigned long flags; 14688c2ecf20Sopenharmony_ci int err = 0; 14698c2ecf20Sopenharmony_ci int nreq; 14708c2ecf20Sopenharmony_ci int ind; 14718c2ecf20Sopenharmony_ci int i; 14728c2ecf20Sopenharmony_ci 14738c2ecf20Sopenharmony_ci if (unlikely(mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR && 14748c2ecf20Sopenharmony_ci !drain)) { 14758c2ecf20Sopenharmony_ci *bad_wr = wr; 14768c2ecf20Sopenharmony_ci return -EIO; 14778c2ecf20Sopenharmony_ci } 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_ci if (unlikely(ibqp->qp_type == IB_QPT_GSI)) 14808c2ecf20Sopenharmony_ci return mlx5_ib_gsi_post_recv(ibqp, wr, bad_wr); 14818c2ecf20Sopenharmony_ci 14828c2ecf20Sopenharmony_ci spin_lock_irqsave(&qp->rq.lock, flags); 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_ci ind = qp->rq.head & (qp->rq.wqe_cnt - 1); 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_ci for (nreq = 0; wr; nreq++, wr = wr->next) { 14878c2ecf20Sopenharmony_ci if (mlx5_wq_overflow(&qp->rq, nreq, qp->ibqp.recv_cq)) { 14888c2ecf20Sopenharmony_ci err = -ENOMEM; 14898c2ecf20Sopenharmony_ci *bad_wr = wr; 14908c2ecf20Sopenharmony_ci goto out; 14918c2ecf20Sopenharmony_ci } 14928c2ecf20Sopenharmony_ci 14938c2ecf20Sopenharmony_ci if (unlikely(wr->num_sge > qp->rq.max_gs)) { 14948c2ecf20Sopenharmony_ci err = -EINVAL; 14958c2ecf20Sopenharmony_ci *bad_wr = wr; 14968c2ecf20Sopenharmony_ci goto out; 14978c2ecf20Sopenharmony_ci } 14988c2ecf20Sopenharmony_ci 14998c2ecf20Sopenharmony_ci scat = mlx5_frag_buf_get_wqe(&qp->rq.fbc, ind); 15008c2ecf20Sopenharmony_ci if (qp->flags_en & MLX5_QP_FLAG_SIGNATURE) 15018c2ecf20Sopenharmony_ci scat++; 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci for (i = 0; i < wr->num_sge; i++) 15048c2ecf20Sopenharmony_ci set_data_ptr_seg(scat + i, wr->sg_list + i); 15058c2ecf20Sopenharmony_ci 15068c2ecf20Sopenharmony_ci if (i < qp->rq.max_gs) { 15078c2ecf20Sopenharmony_ci scat[i].byte_count = 0; 15088c2ecf20Sopenharmony_ci scat[i].lkey = cpu_to_be32(MLX5_INVALID_LKEY); 15098c2ecf20Sopenharmony_ci scat[i].addr = 0; 15108c2ecf20Sopenharmony_ci } 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_ci if (qp->flags_en & MLX5_QP_FLAG_SIGNATURE) { 15138c2ecf20Sopenharmony_ci sig = (struct mlx5_rwqe_sig *)scat; 15148c2ecf20Sopenharmony_ci set_sig_seg(sig, qp->rq.max_gs); 15158c2ecf20Sopenharmony_ci } 15168c2ecf20Sopenharmony_ci 15178c2ecf20Sopenharmony_ci qp->rq.wrid[ind] = wr->wr_id; 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_ci ind = (ind + 1) & (qp->rq.wqe_cnt - 1); 15208c2ecf20Sopenharmony_ci } 15218c2ecf20Sopenharmony_ci 15228c2ecf20Sopenharmony_ciout: 15238c2ecf20Sopenharmony_ci if (likely(nreq)) { 15248c2ecf20Sopenharmony_ci qp->rq.head += nreq; 15258c2ecf20Sopenharmony_ci 15268c2ecf20Sopenharmony_ci /* Make sure that descriptors are written before 15278c2ecf20Sopenharmony_ci * doorbell record. 15288c2ecf20Sopenharmony_ci */ 15298c2ecf20Sopenharmony_ci wmb(); 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_ci *qp->db.db = cpu_to_be32(qp->rq.head & 0xffff); 15328c2ecf20Sopenharmony_ci } 15338c2ecf20Sopenharmony_ci 15348c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->rq.lock, flags); 15358c2ecf20Sopenharmony_ci 15368c2ecf20Sopenharmony_ci return err; 15378c2ecf20Sopenharmony_ci} 1538