diff options
| author | Sagi Grimberg <sagig@mellanox.com> | 2014-02-23 07:19:11 -0500 |
|---|---|---|
| committer | Roland Dreier <roland@purestorage.com> | 2014-03-07 14:39:51 -0500 |
| commit | e6631814fb3ac454fbbf47ea343c2b9508e4e1ba (patch) | |
| tree | dfe554c9fbe5f3f4f0a37276a74180bf2f4e9fd2 | |
| parent | 3bcdb17a5e88288ead90be3c107e754a6075a5b0 (diff) | |
IB/mlx5: Support IB_WR_REG_SIG_MR
This patch implements IB_WR_REG_SIG_MR posted by the user.
Baisically this WR involves 3 WQEs in order to prepare and properly
register the signature layout:
1. post UMR WR to register the sig_mr in one of two possible ways:
* In case the user registered a single MR for data so the UMR data segment
consists of:
- single klm (data MR) passed by the user
- BSF with signature attributes requested by the user.
* In case the user registered 2 MRs, one for data and one for protection,
the UMR consists of:
- strided block format which includes data and protection MRs and
their repetitive block format.
- BSF with signature attributes requested by the user.
2. post SET_PSV in order to set the memory domain initial
signature parameters passed by the user.
SET_PSV is not signaled and solicited CQE.
3. post SET_PSV in order to set the wire domain initial
signature parameters passed by the user.
SET_PSV is not signaled and solicited CQE.
* After this compound WR we place a small fence for next WR to come.
This patch also introduces some helper functions to set the BSF correctly
and determining the signature format selectors.
Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
| -rw-r--r-- | drivers/infiniband/hw/mlx5/qp.c | 422 | ||||
| -rw-r--r-- | include/linux/mlx5/qp.h | 61 |
2 files changed, 483 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index 1dbadbfc4474..67e79989b181 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c | |||
| @@ -1777,6 +1777,26 @@ static __be64 frwr_mkey_mask(void) | |||
| 1777 | return cpu_to_be64(result); | 1777 | return cpu_to_be64(result); |
| 1778 | } | 1778 | } |
| 1779 | 1779 | ||
| 1780 | static __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_RINVAL | | ||
| 1788 | MLX5_MKEY_MASK_KEY | | ||
| 1789 | MLX5_MKEY_MASK_LR | | ||
| 1790 | MLX5_MKEY_MASK_LW | | ||
| 1791 | MLX5_MKEY_MASK_RR | | ||
| 1792 | MLX5_MKEY_MASK_RW | | ||
| 1793 | MLX5_MKEY_MASK_SMALL_FENCE | | ||
| 1794 | MLX5_MKEY_MASK_FREE | | ||
| 1795 | MLX5_MKEY_MASK_BSF_EN; | ||
| 1796 | |||
| 1797 | return cpu_to_be64(result); | ||
| 1798 | } | ||
| 1799 | |||
| 1780 | static void set_frwr_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr, | 1800 | static void set_frwr_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr, |
| 1781 | struct ib_send_wr *wr, int li) | 1801 | struct ib_send_wr *wr, int li) |
| 1782 | { | 1802 | { |
| @@ -1961,6 +1981,339 @@ static int set_data_inl_seg(struct mlx5_ib_qp *qp, struct ib_send_wr *wr, | |||
| 1961 | return 0; | 1981 | return 0; |
| 1962 | } | 1982 | } |
| 1963 | 1983 | ||
| 1984 | static u16 prot_field_size(enum ib_signature_type type) | ||
| 1985 | { | ||
| 1986 | switch (type) { | ||
| 1987 | case IB_SIG_TYPE_T10_DIF: | ||
| 1988 | return MLX5_DIF_SIZE; | ||
| 1989 | default: | ||
| 1990 | return 0; | ||
| 1991 | } | ||
| 1992 | } | ||
| 1993 | |||
| 1994 | static u8 bs_selector(int block_size) | ||
| 1995 | { | ||
| 1996 | switch (block_size) { | ||
| 1997 | case 512: return 0x1; | ||
| 1998 | case 520: return 0x2; | ||
| 1999 | case 4096: return 0x3; | ||
| 2000 | case 4160: return 0x4; | ||
| 2001 | case 1073741824: return 0x5; | ||
| 2002 | default: return 0; | ||
| 2003 | } | ||
| 2004 | } | ||
| 2005 | |||
| 2006 | static int format_selector(struct ib_sig_attrs *attr, | ||
| 2007 | struct ib_sig_domain *domain, | ||
| 2008 | int *selector) | ||
| 2009 | { | ||
| 2010 | |||
| 2011 | #define FORMAT_DIF_NONE 0 | ||
| 2012 | #define FORMAT_DIF_CRC_INC 8 | ||
| 2013 | #define FORMAT_DIF_CRC_NO_INC 12 | ||
| 2014 | #define FORMAT_DIF_CSUM_INC 13 | ||
| 2015 | #define FORMAT_DIF_CSUM_NO_INC 14 | ||
| 2016 | |||
| 2017 | switch (domain->sig.dif.type) { | ||
| 2018 | case IB_T10DIF_NONE: | ||
| 2019 | /* No DIF */ | ||
| 2020 | *selector = FORMAT_DIF_NONE; | ||
| 2021 | break; | ||
| 2022 | case IB_T10DIF_TYPE1: /* Fall through */ | ||
| 2023 | case IB_T10DIF_TYPE2: | ||
| 2024 | switch (domain->sig.dif.bg_type) { | ||
| 2025 | case IB_T10DIF_CRC: | ||
| 2026 | *selector = FORMAT_DIF_CRC_INC; | ||
| 2027 | break; | ||
| 2028 | case IB_T10DIF_CSUM: | ||
| 2029 | *selector = FORMAT_DIF_CSUM_INC; | ||
| 2030 | break; | ||
| 2031 | default: | ||
| 2032 | return 1; | ||
| 2033 | } | ||
| 2034 | break; | ||
| 2035 | case IB_T10DIF_TYPE3: | ||
| 2036 | switch (domain->sig.dif.bg_type) { | ||
| 2037 | case IB_T10DIF_CRC: | ||
| 2038 | *selector = domain->sig.dif.type3_inc_reftag ? | ||
| 2039 | FORMAT_DIF_CRC_INC : | ||
| 2040 | FORMAT_DIF_CRC_NO_INC; | ||
| 2041 | break; | ||
| 2042 | case IB_T10DIF_CSUM: | ||
| 2043 | *selector = domain->sig.dif.type3_inc_reftag ? | ||
| 2044 | FORMAT_DIF_CSUM_INC : | ||
| 2045 | FORMAT_DIF_CSUM_NO_INC; | ||
| 2046 | break; | ||
| 2047 | default: | ||
| 2048 | return 1; | ||
| 2049 | } | ||
| 2050 | break; | ||
| 2051 | default: | ||
| 2052 | return 1; | ||
| 2053 | } | ||
| 2054 | |||
| 2055 | return 0; | ||
| 2056 | } | ||
| 2057 | |||
| 2058 | static int mlx5_set_bsf(struct ib_mr *sig_mr, | ||
| 2059 | struct ib_sig_attrs *sig_attrs, | ||
| 2060 | struct mlx5_bsf *bsf, u32 data_size) | ||
| 2061 | { | ||
| 2062 | struct mlx5_core_sig_ctx *msig = to_mmr(sig_mr)->sig; | ||
| 2063 | struct mlx5_bsf_basic *basic = &bsf->basic; | ||
| 2064 | struct ib_sig_domain *mem = &sig_attrs->mem; | ||
| 2065 | struct ib_sig_domain *wire = &sig_attrs->wire; | ||
| 2066 | int ret, selector; | ||
| 2067 | |||
| 2068 | switch (sig_attrs->mem.sig_type) { | ||
| 2069 | case IB_SIG_TYPE_T10_DIF: | ||
| 2070 | if (sig_attrs->wire.sig_type != IB_SIG_TYPE_T10_DIF) | ||
| 2071 | return -EINVAL; | ||
| 2072 | |||
| 2073 | /* Input domain check byte mask */ | ||
| 2074 | basic->check_byte_mask = sig_attrs->check_mask; | ||
| 2075 | if (mem->sig.dif.pi_interval == wire->sig.dif.pi_interval && | ||
| 2076 | mem->sig.dif.type == wire->sig.dif.type) { | ||
| 2077 | /* Same block structure */ | ||
| 2078 | basic->bsf_size_sbs = 1 << 4; | ||
| 2079 | if (mem->sig.dif.bg_type == wire->sig.dif.bg_type) | ||
| 2080 | basic->wire.copy_byte_mask = 0xff; | ||
| 2081 | else | ||
| 2082 | basic->wire.copy_byte_mask = 0x3f; | ||
| 2083 | } else | ||
| 2084 | basic->wire.bs_selector = bs_selector(wire->sig.dif.pi_interval); | ||
| 2085 | |||
| 2086 | basic->mem.bs_selector = bs_selector(mem->sig.dif.pi_interval); | ||
| 2087 | basic->raw_data_size = cpu_to_be32(data_size); | ||
| 2088 | |||
| 2089 | ret = format_selector(sig_attrs, mem, &selector); | ||
| 2090 | if (ret) | ||
| 2091 | return -EINVAL; | ||
| 2092 | basic->m_bfs_psv = cpu_to_be32(selector << 24 | | ||
| 2093 | msig->psv_memory.psv_idx); | ||
| 2094 | |||
| 2095 | ret = format_selector(sig_attrs, wire, &selector); | ||
| 2096 | if (ret) | ||
| 2097 | return -EINVAL; | ||
| 2098 | basic->w_bfs_psv = cpu_to_be32(selector << 24 | | ||
| 2099 | msig->psv_wire.psv_idx); | ||
| 2100 | break; | ||
| 2101 | |||
| 2102 | default: | ||
| 2103 | return -EINVAL; | ||
| 2104 | } | ||
| 2105 | |||
| 2106 | return 0; | ||
| 2107 | } | ||
| 2108 | |||
| 2109 | static int set_sig_data_segment(struct ib_send_wr *wr, struct mlx5_ib_qp *qp, | ||
| 2110 | void **seg, int *size) | ||
| 2111 | { | ||
| 2112 | struct ib_sig_attrs *sig_attrs = wr->wr.sig_handover.sig_attrs; | ||
| 2113 | struct ib_mr *sig_mr = wr->wr.sig_handover.sig_mr; | ||
| 2114 | struct mlx5_bsf *bsf; | ||
| 2115 | u32 data_len = wr->sg_list->length; | ||
| 2116 | u32 data_key = wr->sg_list->lkey; | ||
| 2117 | u64 data_va = wr->sg_list->addr; | ||
| 2118 | int ret; | ||
| 2119 | int wqe_size; | ||
| 2120 | |||
| 2121 | if (!wr->wr.sig_handover.prot) { | ||
| 2122 | /** | ||
| 2123 | * Source domain doesn't contain signature information | ||
| 2124 | * So need construct: | ||
| 2125 | * ------------------ | ||
| 2126 | * | data_klm | | ||
| 2127 | * ------------------ | ||
| 2128 | * | BSF | | ||
| 2129 | * ------------------ | ||
| 2130 | **/ | ||
| 2131 | struct mlx5_klm *data_klm = *seg; | ||
| 2132 | |||
| 2133 | data_klm->bcount = cpu_to_be32(data_len); | ||
| 2134 | data_klm->key = cpu_to_be32(data_key); | ||
| 2135 | data_klm->va = cpu_to_be64(data_va); | ||
| 2136 | wqe_size = ALIGN(sizeof(*data_klm), 64); | ||
| 2137 | } else { | ||
| 2138 | /** | ||
| 2139 | * Source domain contains signature information | ||
| 2140 | * So need construct a strided block format: | ||
| 2141 | * --------------------------- | ||
| 2142 | * | stride_block_ctrl | | ||
| 2143 | * --------------------------- | ||
| 2144 | * | data_klm | | ||
| 2145 | * --------------------------- | ||
| 2146 | * | prot_klm | | ||
| 2147 | * --------------------------- | ||
| 2148 | * | BSF | | ||
| 2149 | * --------------------------- | ||
| 2150 | **/ | ||
| 2151 | struct mlx5_stride_block_ctrl_seg *sblock_ctrl; | ||
| 2152 | struct mlx5_stride_block_entry *data_sentry; | ||
| 2153 | struct mlx5_stride_block_entry *prot_sentry; | ||
| 2154 | u32 prot_key = wr->wr.sig_handover.prot->lkey; | ||
| 2155 | u64 prot_va = wr->wr.sig_handover.prot->addr; | ||
| 2156 | u16 block_size = sig_attrs->mem.sig.dif.pi_interval; | ||
| 2157 | int prot_size; | ||
| 2158 | |||
| 2159 | sblock_ctrl = *seg; | ||
| 2160 | data_sentry = (void *)sblock_ctrl + sizeof(*sblock_ctrl); | ||
| 2161 | prot_sentry = (void *)data_sentry + sizeof(*data_sentry); | ||
| 2162 | |||
| 2163 | prot_size = prot_field_size(sig_attrs->mem.sig_type); | ||
| 2164 | if (!prot_size) { | ||
| 2165 | pr_err("Bad block size given: %u\n", block_size); | ||
| 2166 | return -EINVAL; | ||
| 2167 | } | ||
| 2168 | sblock_ctrl->bcount_per_cycle = cpu_to_be32(block_size + | ||
| 2169 | prot_size); | ||
| 2170 | sblock_ctrl->op = cpu_to_be32(MLX5_STRIDE_BLOCK_OP); | ||
| 2171 | sblock_ctrl->repeat_count = cpu_to_be32(data_len / block_size); | ||
| 2172 | sblock_ctrl->num_entries = cpu_to_be16(2); | ||
| 2173 | |||
| 2174 | data_sentry->bcount = cpu_to_be16(block_size); | ||
| 2175 | data_sentry->key = cpu_to_be32(data_key); | ||
| 2176 | data_sentry->va = cpu_to_be64(data_va); | ||
| 2177 | prot_sentry->bcount = cpu_to_be16(prot_size); | ||
| 2178 | prot_sentry->key = cpu_to_be32(prot_key); | ||
| 2179 | |||
| 2180 | if (prot_key == data_key && prot_va == data_va) { | ||
| 2181 | /** | ||
| 2182 | * The data and protection are interleaved | ||
| 2183 | * in a single memory region | ||
| 2184 | **/ | ||
| 2185 | prot_sentry->va = cpu_to_be64(data_va + block_size); | ||
| 2186 | prot_sentry->stride = cpu_to_be16(block_size + prot_size); | ||
| 2187 | data_sentry->stride = prot_sentry->stride; | ||
| 2188 | } else { | ||
| 2189 | /* The data and protection are two different buffers */ | ||
| 2190 | prot_sentry->va = cpu_to_be64(prot_va); | ||
| 2191 | data_sentry->stride = cpu_to_be16(block_size); | ||
| 2192 | prot_sentry->stride = cpu_to_be16(prot_size); | ||
| 2193 | } | ||
| 2194 | wqe_size = ALIGN(sizeof(*sblock_ctrl) + sizeof(*data_sentry) + | ||
| 2195 | sizeof(*prot_sentry), 64); | ||
| 2196 | } | ||
| 2197 | |||
| 2198 | *seg += wqe_size; | ||
| 2199 | *size += wqe_size / 16; | ||
| 2200 | if (unlikely((*seg == qp->sq.qend))) | ||
| 2201 | *seg = mlx5_get_send_wqe(qp, 0); | ||
| 2202 | |||
| 2203 | bsf = *seg; | ||
| 2204 | ret = mlx5_set_bsf(sig_mr, sig_attrs, bsf, data_len); | ||
| 2205 | if (ret) | ||
| 2206 | return -EINVAL; | ||
| 2207 | |||
| 2208 | *seg += sizeof(*bsf); | ||
| 2209 | *size += sizeof(*bsf) / 16; | ||
| 2210 | if (unlikely((*seg == qp->sq.qend))) | ||
| 2211 | *seg = mlx5_get_send_wqe(qp, 0); | ||
| 2212 | |||
| 2213 | return 0; | ||
| 2214 | } | ||
| 2215 | |||
| 2216 | static void set_sig_mkey_segment(struct mlx5_mkey_seg *seg, | ||
| 2217 | struct ib_send_wr *wr, u32 nelements, | ||
| 2218 | u32 length, u32 pdn) | ||
| 2219 | { | ||
| 2220 | struct ib_mr *sig_mr = wr->wr.sig_handover.sig_mr; | ||
| 2221 | u32 sig_key = sig_mr->rkey; | ||
| 2222 | |||
| 2223 | memset(seg, 0, sizeof(*seg)); | ||
| 2224 | |||
| 2225 | seg->flags = get_umr_flags(wr->wr.sig_handover.access_flags) | | ||
| 2226 | MLX5_ACCESS_MODE_KLM; | ||
| 2227 | seg->qpn_mkey7_0 = cpu_to_be32((sig_key & 0xff) | 0xffffff00); | ||
| 2228 | seg->flags_pd = cpu_to_be32(MLX5_MKEY_REMOTE_INVAL | | ||
| 2229 | MLX5_MKEY_BSF_EN | pdn); | ||
| 2230 | seg->len = cpu_to_be64(length); | ||
| 2231 | seg->xlt_oct_size = cpu_to_be32(be16_to_cpu(get_klm_octo(nelements))); | ||
| 2232 | seg->bsfs_octo_size = cpu_to_be32(MLX5_MKEY_BSF_OCTO_SIZE); | ||
| 2233 | } | ||
| 2234 | |||
| 2235 | static void set_sig_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr, | ||
| 2236 | struct ib_send_wr *wr, u32 nelements) | ||
| 2237 | { | ||
| 2238 | memset(umr, 0, sizeof(*umr)); | ||
| 2239 | |||
| 2240 | umr->flags = MLX5_FLAGS_INLINE | MLX5_FLAGS_CHECK_FREE; | ||
| 2241 | umr->klm_octowords = get_klm_octo(nelements); | ||
| 2242 | umr->bsf_octowords = cpu_to_be16(MLX5_MKEY_BSF_OCTO_SIZE); | ||
| 2243 | umr->mkey_mask = sig_mkey_mask(); | ||
| 2244 | } | ||
| 2245 | |||
| 2246 | |||
| 2247 | static int set_sig_umr_wr(struct ib_send_wr *wr, struct mlx5_ib_qp *qp, | ||
| 2248 | void **seg, int *size) | ||
| 2249 | { | ||
| 2250 | struct mlx5_ib_mr *sig_mr = to_mmr(wr->wr.sig_handover.sig_mr); | ||
| 2251 | u32 pdn = get_pd(qp)->pdn; | ||
| 2252 | u32 klm_oct_size; | ||
| 2253 | int region_len, ret; | ||
| 2254 | |||
| 2255 | if (unlikely(wr->num_sge != 1) || | ||
| 2256 | unlikely(wr->wr.sig_handover.access_flags & | ||
| 2257 | IB_ACCESS_REMOTE_ATOMIC) || | ||
| 2258 | unlikely(!sig_mr->sig) || unlikely(!qp->signature_en)) | ||
| 2259 | return -EINVAL; | ||
| 2260 | |||
| 2261 | /* length of the protected region, data + protection */ | ||
| 2262 | region_len = wr->sg_list->length; | ||
| 2263 | if (wr->wr.sig_handover.prot) | ||
| 2264 | region_len += wr->wr.sig_handover.prot->length; | ||
| 2265 | |||
| 2266 | /** | ||
| 2267 | * KLM octoword size - if protection was provided | ||
| 2268 | * then we use strided block format (3 octowords), | ||
| 2269 | * else we use single KLM (1 octoword) | ||
| 2270 | **/ | ||
| 2271 | klm_oct_size = wr->wr.sig_handover.prot ? 3 : 1; | ||
| 2272 | |||
| 2273 | set_sig_umr_segment(*seg, wr, klm_oct_size); | ||
| 2274 | *seg += sizeof(struct mlx5_wqe_umr_ctrl_seg); | ||
| 2275 | *size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16; | ||
| 2276 | if (unlikely((*seg == qp->sq.qend))) | ||
| 2277 | *seg = mlx5_get_send_wqe(qp, 0); | ||
| 2278 | |||
| 2279 | set_sig_mkey_segment(*seg, wr, klm_oct_size, region_len, pdn); | ||
| 2280 | *seg += sizeof(struct mlx5_mkey_seg); | ||
| 2281 | *size += sizeof(struct mlx5_mkey_seg) / 16; | ||
| 2282 | if (unlikely((*seg == qp->sq.qend))) | ||
| 2283 | *seg = mlx5_get_send_wqe(qp, 0); | ||
| 2284 | |||
| 2285 | ret = set_sig_data_segment(wr, qp, seg, size); | ||
| 2286 | if (ret) | ||
| 2287 | return ret; | ||
| 2288 | |||
| 2289 | return 0; | ||
| 2290 | } | ||
| 2291 | |||
| 2292 | static int set_psv_wr(struct ib_sig_domain *domain, | ||
| 2293 | u32 psv_idx, void **seg, int *size) | ||
| 2294 | { | ||
| 2295 | struct mlx5_seg_set_psv *psv_seg = *seg; | ||
| 2296 | |||
| 2297 | memset(psv_seg, 0, sizeof(*psv_seg)); | ||
| 2298 | psv_seg->psv_num = cpu_to_be32(psv_idx); | ||
| 2299 | switch (domain->sig_type) { | ||
| 2300 | case IB_SIG_TYPE_T10_DIF: | ||
| 2301 | psv_seg->transient_sig = cpu_to_be32(domain->sig.dif.bg << 16 | | ||
| 2302 | domain->sig.dif.app_tag); | ||
| 2303 | psv_seg->ref_tag = cpu_to_be32(domain->sig.dif.ref_tag); | ||
| 2304 | |||
| 2305 | *seg += sizeof(*psv_seg); | ||
| 2306 | *size += sizeof(*psv_seg) / 16; | ||
| 2307 | break; | ||
| 2308 | |||
| 2309 | default: | ||
| 2310 | pr_err("Bad signature type given.\n"); | ||
| 2311 | return 1; | ||
| 2312 | } | ||
| 2313 | |||
| 2314 | return 0; | ||
| 2315 | } | ||
| 2316 | |||
| 1964 | static int set_frwr_li_wr(void **seg, struct ib_send_wr *wr, int *size, | 2317 | static int set_frwr_li_wr(void **seg, struct ib_send_wr *wr, int *size, |
| 1965 | struct mlx5_core_dev *mdev, struct mlx5_ib_pd *pd, struct mlx5_ib_qp *qp) | 2318 | struct mlx5_core_dev *mdev, struct mlx5_ib_pd *pd, struct mlx5_ib_qp *qp) |
| 1966 | { | 2319 | { |
| @@ -2108,6 +2461,7 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
| 2108 | struct mlx5_ib_dev *dev = to_mdev(ibqp->device); | 2461 | struct mlx5_ib_dev *dev = to_mdev(ibqp->device); |
| 2109 | struct mlx5_core_dev *mdev = &dev->mdev; | 2462 | struct mlx5_core_dev *mdev = &dev->mdev; |
| 2110 | struct mlx5_ib_qp *qp = to_mqp(ibqp); | 2463 | struct mlx5_ib_qp *qp = to_mqp(ibqp); |
| 2464 | struct mlx5_ib_mr *mr; | ||
| 2111 | struct mlx5_wqe_data_seg *dpseg; | 2465 | struct mlx5_wqe_data_seg *dpseg; |
| 2112 | struct mlx5_wqe_xrc_seg *xrc; | 2466 | struct mlx5_wqe_xrc_seg *xrc; |
| 2113 | struct mlx5_bf *bf = qp->bf; | 2467 | struct mlx5_bf *bf = qp->bf; |
| @@ -2203,6 +2557,73 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
| 2203 | num_sge = 0; | 2557 | num_sge = 0; |
| 2204 | break; | 2558 | break; |
| 2205 | 2559 | ||
| 2560 | case IB_WR_REG_SIG_MR: | ||
| 2561 | qp->sq.wr_data[idx] = IB_WR_REG_SIG_MR; | ||
| 2562 | mr = to_mmr(wr->wr.sig_handover.sig_mr); | ||
| 2563 | |||
| 2564 | ctrl->imm = cpu_to_be32(mr->ibmr.rkey); | ||
| 2565 | err = set_sig_umr_wr(wr, qp, &seg, &size); | ||
| 2566 | if (err) { | ||
| 2567 | mlx5_ib_warn(dev, "\n"); | ||
| 2568 | *bad_wr = wr; | ||
| 2569 | goto out; | ||
| 2570 | } | ||
| 2571 | |||
| 2572 | finish_wqe(qp, ctrl, size, idx, wr->wr_id, | ||
| 2573 | nreq, get_fence(fence, wr), | ||
| 2574 | next_fence, MLX5_OPCODE_UMR); | ||
| 2575 | /* | ||
| 2576 | * SET_PSV WQEs are not signaled and solicited | ||
| 2577 | * on error | ||
| 2578 | */ | ||
| 2579 | wr->send_flags &= ~IB_SEND_SIGNALED; | ||
| 2580 | wr->send_flags |= IB_SEND_SOLICITED; | ||
| 2581 | err = begin_wqe(qp, &seg, &ctrl, wr, | ||
| 2582 | &idx, &size, nreq); | ||
| 2583 | if (err) { | ||
| 2584 | mlx5_ib_warn(dev, "\n"); | ||
| 2585 | err = -ENOMEM; | ||
| 2586 | *bad_wr = wr; | ||
| 2587 | goto out; | ||
| 2588 | } | ||
| 2589 | |||
| 2590 | err = set_psv_wr(&wr->wr.sig_handover.sig_attrs->mem, | ||
| 2591 | mr->sig->psv_memory.psv_idx, &seg, | ||
| 2592 | &size); | ||
| 2593 | if (err) { | ||
| 2594 | mlx5_ib_warn(dev, "\n"); | ||
| 2595 | *bad_wr = wr; | ||
| 2596 | goto out; | ||
| 2597 | } | ||
| 2598 | |||
| 2599 | finish_wqe(qp, ctrl, size, idx, wr->wr_id, | ||
| 2600 | nreq, get_fence(fence, wr), | ||
| 2601 | next_fence, MLX5_OPCODE_SET_PSV); | ||
| 2602 | err = begin_wqe(qp, &seg, &ctrl, wr, | ||
| 2603 | &idx, &size, nreq); | ||
| 2604 | if (err) { | ||
| 2605 | mlx5_ib_warn(dev, "\n"); | ||
| 2606 | err = -ENOMEM; | ||
| 2607 | *bad_wr = wr; | ||
| 2608 | goto out; | ||
| 2609 | } | ||
| 2610 | |||
| 2611 | next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL; | ||
| 2612 | err = set_psv_wr(&wr->wr.sig_handover.sig_attrs->wire, | ||
| 2613 | mr->sig->psv_wire.psv_idx, &seg, | ||
| 2614 | &size); | ||
| 2615 | if (err) { | ||
| 2616 | mlx5_ib_warn(dev, "\n"); | ||
| 2617 | *bad_wr = wr; | ||
| 2618 | goto out; | ||
| 2619 | } | ||
| 2620 | |||
| 2621 | finish_wqe(qp, ctrl, size, idx, wr->wr_id, | ||
| 2622 | nreq, get_fence(fence, wr), | ||
| 2623 | next_fence, MLX5_OPCODE_SET_PSV); | ||
| 2624 | num_sge = 0; | ||
| 2625 | goto skip_psv; | ||
| 2626 | |||
| 2206 | default: | 2627 | default: |
| 2207 | break; | 2628 | break; |
| 2208 | } | 2629 | } |
| @@ -2286,6 +2707,7 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
| 2286 | finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq, | 2707 | finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq, |
| 2287 | get_fence(fence, wr), next_fence, | 2708 | get_fence(fence, wr), next_fence, |
| 2288 | mlx5_ib_opcode[wr->opcode]); | 2709 | mlx5_ib_opcode[wr->opcode]); |
| 2710 | skip_psv: | ||
| 2289 | if (0) | 2711 | if (0) |
| 2290 | dump_wqe(qp, idx, size); | 2712 | dump_wqe(qp, idx, size); |
| 2291 | } | 2713 | } |
diff --git a/include/linux/mlx5/qp.h b/include/linux/mlx5/qp.h index 152756eaa8a3..49af74f90ef9 100644 --- a/include/linux/mlx5/qp.h +++ b/include/linux/mlx5/qp.h | |||
| @@ -38,6 +38,8 @@ | |||
| 38 | 38 | ||
| 39 | #define MLX5_INVALID_LKEY 0x100 | 39 | #define MLX5_INVALID_LKEY 0x100 |
| 40 | #define MLX5_SIG_WQE_SIZE (MLX5_SEND_WQE_BB * 5) | 40 | #define MLX5_SIG_WQE_SIZE (MLX5_SEND_WQE_BB * 5) |
| 41 | #define MLX5_DIF_SIZE 8 | ||
| 42 | #define MLX5_STRIDE_BLOCK_OP 0x400 | ||
| 41 | 43 | ||
| 42 | enum mlx5_qp_optpar { | 44 | enum mlx5_qp_optpar { |
| 43 | MLX5_QP_OPTPAR_ALT_ADDR_PATH = 1 << 0, | 45 | MLX5_QP_OPTPAR_ALT_ADDR_PATH = 1 << 0, |
| @@ -152,6 +154,11 @@ enum { | |||
| 152 | MLX5_SND_DBR = 1, | 154 | MLX5_SND_DBR = 1, |
| 153 | }; | 155 | }; |
| 154 | 156 | ||
| 157 | enum { | ||
| 158 | MLX5_FLAGS_INLINE = 1<<7, | ||
| 159 | MLX5_FLAGS_CHECK_FREE = 1<<5, | ||
| 160 | }; | ||
| 161 | |||
| 155 | struct mlx5_wqe_fmr_seg { | 162 | struct mlx5_wqe_fmr_seg { |
| 156 | __be32 flags; | 163 | __be32 flags; |
| 157 | __be32 mem_key; | 164 | __be32 mem_key; |
| @@ -279,6 +286,60 @@ struct mlx5_wqe_inline_seg { | |||
| 279 | __be32 byte_count; | 286 | __be32 byte_count; |
| 280 | }; | 287 | }; |
| 281 | 288 | ||
| 289 | struct mlx5_bsf { | ||
| 290 | struct mlx5_bsf_basic { | ||
| 291 | u8 bsf_size_sbs; | ||
| 292 | u8 check_byte_mask; | ||
| 293 | union { | ||
| 294 | u8 copy_byte_mask; | ||
| 295 | u8 bs_selector; | ||
| 296 | u8 rsvd_wflags; | ||
| 297 | } wire; | ||
| 298 | union { | ||
| 299 | u8 bs_selector; | ||
| 300 | u8 rsvd_mflags; | ||
| 301 | } mem; | ||
| 302 | __be32 raw_data_size; | ||
| 303 | __be32 w_bfs_psv; | ||
| 304 | __be32 m_bfs_psv; | ||
| 305 | } basic; | ||
| 306 | struct mlx5_bsf_ext { | ||
| 307 | __be32 t_init_gen_pro_size; | ||
| 308 | __be32 rsvd_epi_size; | ||
| 309 | __be32 w_tfs_psv; | ||
| 310 | __be32 m_tfs_psv; | ||
| 311 | } ext; | ||
| 312 | struct mlx5_bsf_inl { | ||
| 313 | __be32 w_inl_vld; | ||
| 314 | __be32 w_rsvd; | ||
| 315 | __be64 w_block_format; | ||
| 316 | __be32 m_inl_vld; | ||
| 317 | __be32 m_rsvd; | ||
| 318 | __be64 m_block_format; | ||
| 319 | } inl; | ||
| 320 | }; | ||
| 321 | |||
| 322 | struct mlx5_klm { | ||
| 323 | __be32 bcount; | ||
| 324 | __be32 key; | ||
| 325 | __be64 va; | ||
| 326 | }; | ||
| 327 | |||
| 328 | struct mlx5_stride_block_entry { | ||
| 329 | __be16 stride; | ||
| 330 | __be16 bcount; | ||
| 331 | __be32 key; | ||
| 332 | __be64 va; | ||
| 333 | }; | ||
| 334 | |||
| 335 | struct mlx5_stride_block_ctrl_seg { | ||
| 336 | __be32 bcount_per_cycle; | ||
| 337 | __be32 op; | ||
| 338 | __be32 repeat_count; | ||
| 339 | u16 rsvd; | ||
| 340 | __be16 num_entries; | ||
| 341 | }; | ||
| 342 | |||
| 282 | struct mlx5_core_qp { | 343 | struct mlx5_core_qp { |
| 283 | void (*event) (struct mlx5_core_qp *, int); | 344 | void (*event) (struct mlx5_core_qp *, int); |
| 284 | int qpn; | 345 | int qpn; |
