aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/mlx5/qp.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-04-03 19:57:19 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-03 19:57:19 -0400
commit877f075aac900288ce2e6a64075cceff09210a7e (patch)
tree2bcf23e903403a2bfa3c6fac14d1334614e4d0f1 /drivers/infiniband/hw/mlx5/qp.c
parent3cf59142bcd391680beb6932838fe09a73947705 (diff)
parentf7eaa7ed8fd46542275cf249cd934a366f6556bb (diff)
Merge tag 'rdma-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband
Pull infiniband updates from Roland Dreier: "Main batch of InfiniBand/RDMA changes for 3.15: - The biggest change is core API extensions and mlx5 low-level driver support for handling DIF/DIX-style protection information, and the addition of PI support to the iSER initiator. Target support will be arriving shortly through the SCSI target tree. - A nice simplification to the "umem" memory pinning library now that we have chained sg lists. Kudos to Yishai Hadas for realizing our code didn't have to be so crazy. - Another nice simplification to the sg wrappers used by qib, ipath and ehca to handle their mapping of memory to adapter. - The usual batch of fixes to bugs found by static checkers etc. from intrepid people like Dan Carpenter and Yann Droneaud. - A large batch of cxgb4, ocrdma, qib driver updates" * tag 'rdma-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband: (102 commits) RDMA/ocrdma: Unregister inet notifier when unloading ocrdma RDMA/ocrdma: Fix warnings about pointer <-> integer casts RDMA/ocrdma: Code clean-up RDMA/ocrdma: Display FW version RDMA/ocrdma: Query controller information RDMA/ocrdma: Support non-embedded mailbox commands RDMA/ocrdma: Handle CQ overrun error RDMA/ocrdma: Display proper value for max_mw RDMA/ocrdma: Use non-zero tag in SRQ posting RDMA/ocrdma: Memory leak fix in ocrdma_dereg_mr() RDMA/ocrdma: Increment abi version count RDMA/ocrdma: Update version string be2net: Add abi version between be2net and ocrdma RDMA/ocrdma: ABI versioning between ocrdma and be2net RDMA/ocrdma: Allow DPP QP creation RDMA/ocrdma: Read ASIC_ID register to select asic_gen RDMA/ocrdma: SQ and RQ doorbell offset clean up RDMA/ocrdma: EQ full catastrophe avoidance RDMA/cxgb4: Disable DSGL use by default RDMA/cxgb4: rx_data() needs to hold the ep mutex ...
Diffstat (limited to 'drivers/infiniband/hw/mlx5/qp.c')
-rw-r--r--drivers/infiniband/hw/mlx5/qp.c540
1 files changed, 499 insertions, 41 deletions
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index 7dfe8a1c84cf..ae788d27b93f 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -256,8 +256,11 @@ static int calc_send_wqe(struct ib_qp_init_attr *attr)
256 } 256 }
257 257
258 size += attr->cap.max_send_sge * sizeof(struct mlx5_wqe_data_seg); 258 size += attr->cap.max_send_sge * sizeof(struct mlx5_wqe_data_seg);
259 259 if (attr->create_flags & IB_QP_CREATE_SIGNATURE_EN &&
260 return ALIGN(max_t(int, inl_size, size), MLX5_SEND_WQE_BB); 260 ALIGN(max_t(int, inl_size, size), MLX5_SEND_WQE_BB) < MLX5_SIG_WQE_SIZE)
261 return MLX5_SIG_WQE_SIZE;
262 else
263 return ALIGN(max_t(int, inl_size, size), MLX5_SEND_WQE_BB);
261} 264}
262 265
263static int calc_sq_size(struct mlx5_ib_dev *dev, struct ib_qp_init_attr *attr, 266static int calc_sq_size(struct mlx5_ib_dev *dev, struct ib_qp_init_attr *attr,
@@ -284,6 +287,9 @@ static int calc_sq_size(struct mlx5_ib_dev *dev, struct ib_qp_init_attr *attr,
284 sizeof(struct mlx5_wqe_inline_seg); 287 sizeof(struct mlx5_wqe_inline_seg);
285 attr->cap.max_inline_data = qp->max_inline_data; 288 attr->cap.max_inline_data = qp->max_inline_data;
286 289
290 if (attr->create_flags & IB_QP_CREATE_SIGNATURE_EN)
291 qp->signature_en = true;
292
287 wq_size = roundup_pow_of_two(attr->cap.max_send_wr * wqe_size); 293 wq_size = roundup_pow_of_two(attr->cap.max_send_wr * wqe_size);
288 qp->sq.wqe_cnt = wq_size / MLX5_SEND_WQE_BB; 294 qp->sq.wqe_cnt = wq_size / MLX5_SEND_WQE_BB;
289 if (qp->sq.wqe_cnt > dev->mdev.caps.max_wqes) { 295 if (qp->sq.wqe_cnt > dev->mdev.caps.max_wqes) {
@@ -665,7 +671,7 @@ static int create_kernel_qp(struct mlx5_ib_dev *dev,
665 int err; 671 int err;
666 672
667 uuari = &dev->mdev.priv.uuari; 673 uuari = &dev->mdev.priv.uuari;
668 if (init_attr->create_flags) 674 if (init_attr->create_flags & ~IB_QP_CREATE_SIGNATURE_EN)
669 return -EINVAL; 675 return -EINVAL;
670 676
671 if (init_attr->qp_type == MLX5_IB_QPT_REG_UMR) 677 if (init_attr->qp_type == MLX5_IB_QPT_REG_UMR)
@@ -1771,6 +1777,27 @@ static __be64 frwr_mkey_mask(void)
1771 return cpu_to_be64(result); 1777 return cpu_to_be64(result);
1772} 1778}
1773 1779
1780static __be64 sig_mkey_mask(void)
1781{
1782 u64 result;
1783
1784 result = MLX5_MKEY_MASK_LEN |
1785 MLX5_MKEY_MASK_PAGE_SIZE |
1786 MLX5_MKEY_MASK_START_ADDR |
1787 MLX5_MKEY_MASK_EN_SIGERR |
1788 MLX5_MKEY_MASK_EN_RINVAL |
1789 MLX5_MKEY_MASK_KEY |
1790 MLX5_MKEY_MASK_LR |
1791 MLX5_MKEY_MASK_LW |
1792 MLX5_MKEY_MASK_RR |
1793 MLX5_MKEY_MASK_RW |
1794 MLX5_MKEY_MASK_SMALL_FENCE |
1795 MLX5_MKEY_MASK_FREE |
1796 MLX5_MKEY_MASK_BSF_EN;
1797
1798 return cpu_to_be64(result);
1799}
1800
1774static void set_frwr_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr, 1801static void set_frwr_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr,
1775 struct ib_send_wr *wr, int li) 1802 struct ib_send_wr *wr, int li)
1776{ 1803{
@@ -1826,7 +1853,7 @@ static u8 get_umr_flags(int acc)
1826 (acc & IB_ACCESS_REMOTE_WRITE ? MLX5_PERM_REMOTE_WRITE : 0) | 1853 (acc & IB_ACCESS_REMOTE_WRITE ? MLX5_PERM_REMOTE_WRITE : 0) |
1827 (acc & IB_ACCESS_REMOTE_READ ? MLX5_PERM_REMOTE_READ : 0) | 1854 (acc & IB_ACCESS_REMOTE_READ ? MLX5_PERM_REMOTE_READ : 0) |
1828 (acc & IB_ACCESS_LOCAL_WRITE ? MLX5_PERM_LOCAL_WRITE : 0) | 1855 (acc & IB_ACCESS_LOCAL_WRITE ? MLX5_PERM_LOCAL_WRITE : 0) |
1829 MLX5_PERM_LOCAL_READ | MLX5_PERM_UMR_EN | MLX5_ACCESS_MODE_MTT; 1856 MLX5_PERM_LOCAL_READ | MLX5_PERM_UMR_EN;
1830} 1857}
1831 1858
1832static void set_mkey_segment(struct mlx5_mkey_seg *seg, struct ib_send_wr *wr, 1859static void set_mkey_segment(struct mlx5_mkey_seg *seg, struct ib_send_wr *wr,
@@ -1838,7 +1865,8 @@ static void set_mkey_segment(struct mlx5_mkey_seg *seg, struct ib_send_wr *wr,
1838 return; 1865 return;
1839 } 1866 }
1840 1867
1841 seg->flags = get_umr_flags(wr->wr.fast_reg.access_flags); 1868 seg->flags = get_umr_flags(wr->wr.fast_reg.access_flags) |
1869 MLX5_ACCESS_MODE_MTT;
1842 *writ = seg->flags & (MLX5_PERM_LOCAL_WRITE | IB_ACCESS_REMOTE_WRITE); 1870 *writ = seg->flags & (MLX5_PERM_LOCAL_WRITE | IB_ACCESS_REMOTE_WRITE);
1843 seg->qpn_mkey7_0 = cpu_to_be32((wr->wr.fast_reg.rkey & 0xff) | 0xffffff00); 1871 seg->qpn_mkey7_0 = cpu_to_be32((wr->wr.fast_reg.rkey & 0xff) | 0xffffff00);
1844 seg->flags_pd = cpu_to_be32(MLX5_MKEY_REMOTE_INVAL); 1872 seg->flags_pd = cpu_to_be32(MLX5_MKEY_REMOTE_INVAL);
@@ -1954,6 +1982,342 @@ static int set_data_inl_seg(struct mlx5_ib_qp *qp, struct ib_send_wr *wr,
1954 return 0; 1982 return 0;
1955} 1983}
1956 1984
1985static u16 prot_field_size(enum ib_signature_type type)
1986{
1987 switch (type) {
1988 case IB_SIG_TYPE_T10_DIF:
1989 return MLX5_DIF_SIZE;
1990 default:
1991 return 0;
1992 }
1993}
1994
1995static u8 bs_selector(int block_size)
1996{
1997 switch (block_size) {
1998 case 512: return 0x1;
1999 case 520: return 0x2;
2000 case 4096: return 0x3;
2001 case 4160: return 0x4;
2002 case 1073741824: return 0x5;
2003 default: return 0;
2004 }
2005}
2006
2007static int format_selector(struct ib_sig_attrs *attr,
2008 struct ib_sig_domain *domain,
2009 int *selector)
2010{
2011
2012#define FORMAT_DIF_NONE 0
2013#define FORMAT_DIF_CRC_INC 8
2014#define FORMAT_DIF_CRC_NO_INC 12
2015#define FORMAT_DIF_CSUM_INC 13
2016#define FORMAT_DIF_CSUM_NO_INC 14
2017
2018 switch (domain->sig.dif.type) {
2019 case IB_T10DIF_NONE:
2020 /* No DIF */
2021 *selector = FORMAT_DIF_NONE;
2022 break;
2023 case IB_T10DIF_TYPE1: /* Fall through */
2024 case IB_T10DIF_TYPE2:
2025 switch (domain->sig.dif.bg_type) {
2026 case IB_T10DIF_CRC:
2027 *selector = FORMAT_DIF_CRC_INC;
2028 break;
2029 case IB_T10DIF_CSUM:
2030 *selector = FORMAT_DIF_CSUM_INC;
2031 break;
2032 default:
2033 return 1;
2034 }
2035 break;
2036 case IB_T10DIF_TYPE3:
2037 switch (domain->sig.dif.bg_type) {
2038 case IB_T10DIF_CRC:
2039 *selector = domain->sig.dif.type3_inc_reftag ?
2040 FORMAT_DIF_CRC_INC :
2041 FORMAT_DIF_CRC_NO_INC;
2042 break;
2043 case IB_T10DIF_CSUM:
2044 *selector = domain->sig.dif.type3_inc_reftag ?
2045 FORMAT_DIF_CSUM_INC :
2046 FORMAT_DIF_CSUM_NO_INC;
2047 break;
2048 default:
2049 return 1;
2050 }
2051 break;
2052 default:
2053 return 1;
2054 }
2055
2056 return 0;
2057}
2058
2059static int mlx5_set_bsf(struct ib_mr *sig_mr,
2060 struct ib_sig_attrs *sig_attrs,
2061 struct mlx5_bsf *bsf, u32 data_size)
2062{
2063 struct mlx5_core_sig_ctx *msig = to_mmr(sig_mr)->sig;
2064 struct mlx5_bsf_basic *basic = &bsf->basic;
2065 struct ib_sig_domain *mem = &sig_attrs->mem;
2066 struct ib_sig_domain *wire = &sig_attrs->wire;
2067 int ret, selector;
2068
2069 switch (sig_attrs->mem.sig_type) {
2070 case IB_SIG_TYPE_T10_DIF:
2071 if (sig_attrs->wire.sig_type != IB_SIG_TYPE_T10_DIF)
2072 return -EINVAL;
2073
2074 /* Input domain check byte mask */
2075 basic->check_byte_mask = sig_attrs->check_mask;
2076 if (mem->sig.dif.pi_interval == wire->sig.dif.pi_interval &&
2077 mem->sig.dif.type == wire->sig.dif.type) {
2078 /* Same block structure */
2079 basic->bsf_size_sbs = 1 << 4;
2080 if (mem->sig.dif.bg_type == wire->sig.dif.bg_type)
2081 basic->wire.copy_byte_mask = 0xff;
2082 else
2083 basic->wire.copy_byte_mask = 0x3f;
2084 } else
2085 basic->wire.bs_selector = bs_selector(wire->sig.dif.pi_interval);
2086
2087 basic->mem.bs_selector = bs_selector(mem->sig.dif.pi_interval);
2088 basic->raw_data_size = cpu_to_be32(data_size);
2089
2090 ret = format_selector(sig_attrs, mem, &selector);
2091 if (ret)
2092 return -EINVAL;
2093 basic->m_bfs_psv = cpu_to_be32(selector << 24 |
2094 msig->psv_memory.psv_idx);
2095
2096 ret = format_selector(sig_attrs, wire, &selector);
2097 if (ret)
2098 return -EINVAL;
2099 basic->w_bfs_psv = cpu_to_be32(selector << 24 |
2100 msig->psv_wire.psv_idx);
2101 break;
2102
2103 default:
2104 return -EINVAL;
2105 }
2106
2107 return 0;
2108}
2109
2110static int set_sig_data_segment(struct ib_send_wr *wr, struct mlx5_ib_qp *qp,
2111 void **seg, int *size)
2112{
2113 struct ib_sig_attrs *sig_attrs = wr->wr.sig_handover.sig_attrs;
2114 struct ib_mr *sig_mr = wr->wr.sig_handover.sig_mr;
2115 struct mlx5_bsf *bsf;
2116 u32 data_len = wr->sg_list->length;
2117 u32 data_key = wr->sg_list->lkey;
2118 u64 data_va = wr->sg_list->addr;
2119 int ret;
2120 int wqe_size;
2121
2122 if (!wr->wr.sig_handover.prot) {
2123 /**
2124 * Source domain doesn't contain signature information
2125 * So need construct:
2126 * ------------------
2127 * | data_klm |
2128 * ------------------
2129 * | BSF |
2130 * ------------------
2131 **/
2132 struct mlx5_klm *data_klm = *seg;
2133
2134 data_klm->bcount = cpu_to_be32(data_len);
2135 data_klm->key = cpu_to_be32(data_key);
2136 data_klm->va = cpu_to_be64(data_va);
2137 wqe_size = ALIGN(sizeof(*data_klm), 64);
2138 } else {
2139 /**
2140 * Source domain contains signature information
2141 * So need construct a strided block format:
2142 * ---------------------------
2143 * | stride_block_ctrl |
2144 * ---------------------------
2145 * | data_klm |
2146 * ---------------------------
2147 * | prot_klm |
2148 * ---------------------------
2149 * | BSF |
2150 * ---------------------------
2151 **/
2152 struct mlx5_stride_block_ctrl_seg *sblock_ctrl;
2153 struct mlx5_stride_block_entry *data_sentry;
2154 struct mlx5_stride_block_entry *prot_sentry;
2155 u32 prot_key = wr->wr.sig_handover.prot->lkey;
2156 u64 prot_va = wr->wr.sig_handover.prot->addr;
2157 u16 block_size = sig_attrs->mem.sig.dif.pi_interval;
2158 int prot_size;
2159
2160 sblock_ctrl = *seg;
2161 data_sentry = (void *)sblock_ctrl + sizeof(*sblock_ctrl);
2162 prot_sentry = (void *)data_sentry + sizeof(*data_sentry);
2163
2164 prot_size = prot_field_size(sig_attrs->mem.sig_type);
2165 if (!prot_size) {
2166 pr_err("Bad block size given: %u\n", block_size);
2167 return -EINVAL;
2168 }
2169 sblock_ctrl->bcount_per_cycle = cpu_to_be32(block_size +
2170 prot_size);
2171 sblock_ctrl->op = cpu_to_be32(MLX5_STRIDE_BLOCK_OP);
2172 sblock_ctrl->repeat_count = cpu_to_be32(data_len / block_size);
2173 sblock_ctrl->num_entries = cpu_to_be16(2);
2174
2175 data_sentry->bcount = cpu_to_be16(block_size);
2176 data_sentry->key = cpu_to_be32(data_key);
2177 data_sentry->va = cpu_to_be64(data_va);
2178 prot_sentry->bcount = cpu_to_be16(prot_size);
2179 prot_sentry->key = cpu_to_be32(prot_key);
2180
2181 if (prot_key == data_key && prot_va == data_va) {
2182 /**
2183 * The data and protection are interleaved
2184 * in a single memory region
2185 **/
2186 prot_sentry->va = cpu_to_be64(data_va + block_size);
2187 prot_sentry->stride = cpu_to_be16(block_size + prot_size);
2188 data_sentry->stride = prot_sentry->stride;
2189 } else {
2190 /* The data and protection are two different buffers */
2191 prot_sentry->va = cpu_to_be64(prot_va);
2192 data_sentry->stride = cpu_to_be16(block_size);
2193 prot_sentry->stride = cpu_to_be16(prot_size);
2194 }
2195 wqe_size = ALIGN(sizeof(*sblock_ctrl) + sizeof(*data_sentry) +
2196 sizeof(*prot_sentry), 64);
2197 }
2198
2199 *seg += wqe_size;
2200 *size += wqe_size / 16;
2201 if (unlikely((*seg == qp->sq.qend)))
2202 *seg = mlx5_get_send_wqe(qp, 0);
2203
2204 bsf = *seg;
2205 ret = mlx5_set_bsf(sig_mr, sig_attrs, bsf, data_len);
2206 if (ret)
2207 return -EINVAL;
2208
2209 *seg += sizeof(*bsf);
2210 *size += sizeof(*bsf) / 16;
2211 if (unlikely((*seg == qp->sq.qend)))
2212 *seg = mlx5_get_send_wqe(qp, 0);
2213
2214 return 0;
2215}
2216
2217static void set_sig_mkey_segment(struct mlx5_mkey_seg *seg,
2218 struct ib_send_wr *wr, u32 nelements,
2219 u32 length, u32 pdn)
2220{
2221 struct ib_mr *sig_mr = wr->wr.sig_handover.sig_mr;
2222 u32 sig_key = sig_mr->rkey;
2223 u8 sigerr = to_mmr(sig_mr)->sig->sigerr_count & 1;
2224
2225 memset(seg, 0, sizeof(*seg));
2226
2227 seg->flags = get_umr_flags(wr->wr.sig_handover.access_flags) |
2228 MLX5_ACCESS_MODE_KLM;
2229 seg->qpn_mkey7_0 = cpu_to_be32((sig_key & 0xff) | 0xffffff00);
2230 seg->flags_pd = cpu_to_be32(MLX5_MKEY_REMOTE_INVAL | sigerr << 26 |
2231 MLX5_MKEY_BSF_EN | pdn);
2232 seg->len = cpu_to_be64(length);
2233 seg->xlt_oct_size = cpu_to_be32(be16_to_cpu(get_klm_octo(nelements)));
2234 seg->bsfs_octo_size = cpu_to_be32(MLX5_MKEY_BSF_OCTO_SIZE);
2235}
2236
2237static void set_sig_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr,
2238 struct ib_send_wr *wr, u32 nelements)
2239{
2240 memset(umr, 0, sizeof(*umr));
2241
2242 umr->flags = MLX5_FLAGS_INLINE | MLX5_FLAGS_CHECK_FREE;
2243 umr->klm_octowords = get_klm_octo(nelements);
2244 umr->bsf_octowords = cpu_to_be16(MLX5_MKEY_BSF_OCTO_SIZE);
2245 umr->mkey_mask = sig_mkey_mask();
2246}
2247
2248
2249static int set_sig_umr_wr(struct ib_send_wr *wr, struct mlx5_ib_qp *qp,
2250 void **seg, int *size)
2251{
2252 struct mlx5_ib_mr *sig_mr = to_mmr(wr->wr.sig_handover.sig_mr);
2253 u32 pdn = get_pd(qp)->pdn;
2254 u32 klm_oct_size;
2255 int region_len, ret;
2256
2257 if (unlikely(wr->num_sge != 1) ||
2258 unlikely(wr->wr.sig_handover.access_flags &
2259 IB_ACCESS_REMOTE_ATOMIC) ||
2260 unlikely(!sig_mr->sig) || unlikely(!qp->signature_en) ||
2261 unlikely(!sig_mr->sig->sig_status_checked))
2262 return -EINVAL;
2263
2264 /* length of the protected region, data + protection */
2265 region_len = wr->sg_list->length;
2266 if (wr->wr.sig_handover.prot)
2267 region_len += wr->wr.sig_handover.prot->length;
2268
2269 /**
2270 * KLM octoword size - if protection was provided
2271 * then we use strided block format (3 octowords),
2272 * else we use single KLM (1 octoword)
2273 **/
2274 klm_oct_size = wr->wr.sig_handover.prot ? 3 : 1;
2275
2276 set_sig_umr_segment(*seg, wr, klm_oct_size);
2277 *seg += sizeof(struct mlx5_wqe_umr_ctrl_seg);
2278 *size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16;
2279 if (unlikely((*seg == qp->sq.qend)))
2280 *seg = mlx5_get_send_wqe(qp, 0);
2281
2282 set_sig_mkey_segment(*seg, wr, klm_oct_size, region_len, pdn);
2283 *seg += sizeof(struct mlx5_mkey_seg);
2284 *size += sizeof(struct mlx5_mkey_seg) / 16;
2285 if (unlikely((*seg == qp->sq.qend)))
2286 *seg = mlx5_get_send_wqe(qp, 0);
2287
2288 ret = set_sig_data_segment(wr, qp, seg, size);
2289 if (ret)
2290 return ret;
2291
2292 sig_mr->sig->sig_status_checked = false;
2293 return 0;
2294}
2295
2296static int set_psv_wr(struct ib_sig_domain *domain,
2297 u32 psv_idx, void **seg, int *size)
2298{
2299 struct mlx5_seg_set_psv *psv_seg = *seg;
2300
2301 memset(psv_seg, 0, sizeof(*psv_seg));
2302 psv_seg->psv_num = cpu_to_be32(psv_idx);
2303 switch (domain->sig_type) {
2304 case IB_SIG_TYPE_T10_DIF:
2305 psv_seg->transient_sig = cpu_to_be32(domain->sig.dif.bg << 16 |
2306 domain->sig.dif.app_tag);
2307 psv_seg->ref_tag = cpu_to_be32(domain->sig.dif.ref_tag);
2308
2309 *seg += sizeof(*psv_seg);
2310 *size += sizeof(*psv_seg) / 16;
2311 break;
2312
2313 default:
2314 pr_err("Bad signature type given.\n");
2315 return 1;
2316 }
2317
2318 return 0;
2319}
2320
1957static int set_frwr_li_wr(void **seg, struct ib_send_wr *wr, int *size, 2321static int set_frwr_li_wr(void **seg, struct ib_send_wr *wr, int *size,
1958 struct mlx5_core_dev *mdev, struct mlx5_ib_pd *pd, struct mlx5_ib_qp *qp) 2322 struct mlx5_core_dev *mdev, struct mlx5_ib_pd *pd, struct mlx5_ib_qp *qp)
1959{ 2323{
@@ -2041,6 +2405,59 @@ static u8 get_fence(u8 fence, struct ib_send_wr *wr)
2041 } 2405 }
2042} 2406}
2043 2407
2408static int begin_wqe(struct mlx5_ib_qp *qp, void **seg,
2409 struct mlx5_wqe_ctrl_seg **ctrl,
2410 struct ib_send_wr *wr, int *idx,
2411 int *size, int nreq)
2412{
2413 int err = 0;
2414
2415 if (unlikely(mlx5_wq_overflow(&qp->sq, nreq, qp->ibqp.send_cq))) {
2416 err = -ENOMEM;
2417 return err;
2418 }
2419
2420 *idx = qp->sq.cur_post & (qp->sq.wqe_cnt - 1);
2421 *seg = mlx5_get_send_wqe(qp, *idx);
2422 *ctrl = *seg;
2423 *(uint32_t *)(*seg + 8) = 0;
2424 (*ctrl)->imm = send_ieth(wr);
2425 (*ctrl)->fm_ce_se = qp->sq_signal_bits |
2426 (wr->send_flags & IB_SEND_SIGNALED ?
2427 MLX5_WQE_CTRL_CQ_UPDATE : 0) |
2428 (wr->send_flags & IB_SEND_SOLICITED ?
2429 MLX5_WQE_CTRL_SOLICITED : 0);
2430
2431 *seg += sizeof(**ctrl);
2432 *size = sizeof(**ctrl) / 16;
2433
2434 return err;
2435}
2436
2437static void finish_wqe(struct mlx5_ib_qp *qp,
2438 struct mlx5_wqe_ctrl_seg *ctrl,
2439 u8 size, unsigned idx, u64 wr_id,
2440 int nreq, u8 fence, u8 next_fence,
2441 u32 mlx5_opcode)
2442{
2443 u8 opmod = 0;
2444
2445 ctrl->opmod_idx_opcode = cpu_to_be32(((u32)(qp->sq.cur_post) << 8) |
2446 mlx5_opcode | ((u32)opmod << 24));
2447 ctrl->qpn_ds = cpu_to_be32(size | (qp->mqp.qpn << 8));
2448 ctrl->fm_ce_se |= fence;
2449 qp->fm_cache = next_fence;
2450 if (unlikely(qp->wq_sig))
2451 ctrl->signature = wq_sig(ctrl);
2452
2453 qp->sq.wrid[idx] = wr_id;
2454 qp->sq.w_list[idx].opcode = mlx5_opcode;
2455 qp->sq.wqe_head[idx] = qp->sq.head + nreq;
2456 qp->sq.cur_post += DIV_ROUND_UP(size * 16, MLX5_SEND_WQE_BB);
2457 qp->sq.w_list[idx].next = qp->sq.cur_post;
2458}
2459
2460
2044int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, 2461int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
2045 struct ib_send_wr **bad_wr) 2462 struct ib_send_wr **bad_wr)
2046{ 2463{
@@ -2048,13 +2465,13 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
2048 struct mlx5_ib_dev *dev = to_mdev(ibqp->device); 2465 struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
2049 struct mlx5_core_dev *mdev = &dev->mdev; 2466 struct mlx5_core_dev *mdev = &dev->mdev;
2050 struct mlx5_ib_qp *qp = to_mqp(ibqp); 2467 struct mlx5_ib_qp *qp = to_mqp(ibqp);
2468 struct mlx5_ib_mr *mr;
2051 struct mlx5_wqe_data_seg *dpseg; 2469 struct mlx5_wqe_data_seg *dpseg;
2052 struct mlx5_wqe_xrc_seg *xrc; 2470 struct mlx5_wqe_xrc_seg *xrc;
2053 struct mlx5_bf *bf = qp->bf; 2471 struct mlx5_bf *bf = qp->bf;
2054 int uninitialized_var(size); 2472 int uninitialized_var(size);
2055 void *qend = qp->sq.qend; 2473 void *qend = qp->sq.qend;
2056 unsigned long flags; 2474 unsigned long flags;
2057 u32 mlx5_opcode;
2058 unsigned idx; 2475 unsigned idx;
2059 int err = 0; 2476 int err = 0;
2060 int inl = 0; 2477 int inl = 0;
@@ -2063,7 +2480,6 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
2063 int nreq; 2480 int nreq;
2064 int i; 2481 int i;
2065 u8 next_fence = 0; 2482 u8 next_fence = 0;
2066 u8 opmod = 0;
2067 u8 fence; 2483 u8 fence;
2068 2484
2069 spin_lock_irqsave(&qp->sq.lock, flags); 2485 spin_lock_irqsave(&qp->sq.lock, flags);
@@ -2076,36 +2492,23 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
2076 goto out; 2492 goto out;
2077 } 2493 }
2078 2494
2079 if (unlikely(mlx5_wq_overflow(&qp->sq, nreq, qp->ibqp.send_cq))) { 2495 fence = qp->fm_cache;
2496 num_sge = wr->num_sge;
2497 if (unlikely(num_sge > qp->sq.max_gs)) {
2080 mlx5_ib_warn(dev, "\n"); 2498 mlx5_ib_warn(dev, "\n");
2081 err = -ENOMEM; 2499 err = -ENOMEM;
2082 *bad_wr = wr; 2500 *bad_wr = wr;
2083 goto out; 2501 goto out;
2084 } 2502 }
2085 2503
2086 fence = qp->fm_cache; 2504 err = begin_wqe(qp, &seg, &ctrl, wr, &idx, &size, nreq);
2087 num_sge = wr->num_sge; 2505 if (err) {
2088 if (unlikely(num_sge > qp->sq.max_gs)) {
2089 mlx5_ib_warn(dev, "\n"); 2506 mlx5_ib_warn(dev, "\n");
2090 err = -ENOMEM; 2507 err = -ENOMEM;
2091 *bad_wr = wr; 2508 *bad_wr = wr;
2092 goto out; 2509 goto out;
2093 } 2510 }
2094 2511
2095 idx = qp->sq.cur_post & (qp->sq.wqe_cnt - 1);
2096 seg = mlx5_get_send_wqe(qp, idx);
2097 ctrl = seg;
2098 *(uint32_t *)(seg + 8) = 0;
2099 ctrl->imm = send_ieth(wr);
2100 ctrl->fm_ce_se = qp->sq_signal_bits |
2101 (wr->send_flags & IB_SEND_SIGNALED ?
2102 MLX5_WQE_CTRL_CQ_UPDATE : 0) |
2103 (wr->send_flags & IB_SEND_SOLICITED ?
2104 MLX5_WQE_CTRL_SOLICITED : 0);
2105
2106 seg += sizeof(*ctrl);
2107 size = sizeof(*ctrl) / 16;
2108
2109 switch (ibqp->qp_type) { 2512 switch (ibqp->qp_type) {
2110 case IB_QPT_XRC_INI: 2513 case IB_QPT_XRC_INI:
2111 xrc = seg; 2514 xrc = seg;
@@ -2158,6 +2561,73 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
2158 num_sge = 0; 2561 num_sge = 0;
2159 break; 2562 break;
2160 2563
2564 case IB_WR_REG_SIG_MR:
2565 qp->sq.wr_data[idx] = IB_WR_REG_SIG_MR;
2566 mr = to_mmr(wr->wr.sig_handover.sig_mr);
2567
2568 ctrl->imm = cpu_to_be32(mr->ibmr.rkey);
2569 err = set_sig_umr_wr(wr, qp, &seg, &size);
2570 if (err) {
2571 mlx5_ib_warn(dev, "\n");
2572 *bad_wr = wr;
2573 goto out;
2574 }
2575
2576 finish_wqe(qp, ctrl, size, idx, wr->wr_id,
2577 nreq, get_fence(fence, wr),
2578 next_fence, MLX5_OPCODE_UMR);
2579 /*
2580 * SET_PSV WQEs are not signaled and solicited
2581 * on error
2582 */
2583 wr->send_flags &= ~IB_SEND_SIGNALED;
2584 wr->send_flags |= IB_SEND_SOLICITED;
2585 err = begin_wqe(qp, &seg, &ctrl, wr,
2586 &idx, &size, nreq);
2587 if (err) {
2588 mlx5_ib_warn(dev, "\n");
2589 err = -ENOMEM;
2590 *bad_wr = wr;
2591 goto out;
2592 }
2593
2594 err = set_psv_wr(&wr->wr.sig_handover.sig_attrs->mem,
2595 mr->sig->psv_memory.psv_idx, &seg,
2596 &size);
2597 if (err) {
2598 mlx5_ib_warn(dev, "\n");
2599 *bad_wr = wr;
2600 goto out;
2601 }
2602
2603 finish_wqe(qp, ctrl, size, idx, wr->wr_id,
2604 nreq, get_fence(fence, wr),
2605 next_fence, MLX5_OPCODE_SET_PSV);
2606 err = begin_wqe(qp, &seg, &ctrl, wr,
2607 &idx, &size, nreq);
2608 if (err) {
2609 mlx5_ib_warn(dev, "\n");
2610 err = -ENOMEM;
2611 *bad_wr = wr;
2612 goto out;
2613 }
2614
2615 next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
2616 err = set_psv_wr(&wr->wr.sig_handover.sig_attrs->wire,
2617 mr->sig->psv_wire.psv_idx, &seg,
2618 &size);
2619 if (err) {
2620 mlx5_ib_warn(dev, "\n");
2621 *bad_wr = wr;
2622 goto out;
2623 }
2624
2625 finish_wqe(qp, ctrl, size, idx, wr->wr_id,
2626 nreq, get_fence(fence, wr),
2627 next_fence, MLX5_OPCODE_SET_PSV);
2628 num_sge = 0;
2629 goto skip_psv;
2630
2161 default: 2631 default:
2162 break; 2632 break;
2163 } 2633 }
@@ -2238,22 +2708,10 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
2238 } 2708 }
2239 } 2709 }
2240 2710
2241 mlx5_opcode = mlx5_ib_opcode[wr->opcode]; 2711 finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq,
2242 ctrl->opmod_idx_opcode = cpu_to_be32(((u32)(qp->sq.cur_post) << 8) | 2712 get_fence(fence, wr), next_fence,
2243 mlx5_opcode | 2713 mlx5_ib_opcode[wr->opcode]);
2244 ((u32)opmod << 24)); 2714skip_psv:
2245 ctrl->qpn_ds = cpu_to_be32(size | (qp->mqp.qpn << 8));
2246 ctrl->fm_ce_se |= get_fence(fence, wr);
2247 qp->fm_cache = next_fence;
2248 if (unlikely(qp->wq_sig))
2249 ctrl->signature = wq_sig(ctrl);
2250
2251 qp->sq.wrid[idx] = wr->wr_id;
2252 qp->sq.w_list[idx].opcode = mlx5_opcode;
2253 qp->sq.wqe_head[idx] = qp->sq.head + nreq;
2254 qp->sq.cur_post += DIV_ROUND_UP(size * 16, MLX5_SEND_WQE_BB);
2255 qp->sq.w_list[idx].next = qp->sq.cur_post;
2256
2257 if (0) 2715 if (0)
2258 dump_wqe(qp, idx, size); 2716 dump_wqe(qp, idx, size);
2259 } 2717 }