diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-03 19:57:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-03 19:57:19 -0400 |
commit | 877f075aac900288ce2e6a64075cceff09210a7e (patch) | |
tree | 2bcf23e903403a2bfa3c6fac14d1334614e4d0f1 /drivers/infiniband/hw/mlx5/qp.c | |
parent | 3cf59142bcd391680beb6932838fe09a73947705 (diff) | |
parent | f7eaa7ed8fd46542275cf249cd934a366f6556bb (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.c | 540 |
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 | ||
263 | static int calc_sq_size(struct mlx5_ib_dev *dev, struct ib_qp_init_attr *attr, | 266 | static 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 | ||
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_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 | |||
1774 | static void set_frwr_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr, | 1801 | static 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 | ||
1832 | static void set_mkey_segment(struct mlx5_mkey_seg *seg, struct ib_send_wr *wr, | 1859 | static 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 | ||
1985 | static 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 | |||
1995 | static 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 | |||
2007 | static 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 | |||
2059 | static 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 | |||
2110 | static 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 | |||
2217 | static 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 | |||
2237 | static 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 | |||
2249 | static 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 | |||
2296 | static 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 | |||
1957 | static int set_frwr_li_wr(void **seg, struct ib_send_wr *wr, int *size, | 2321 | static 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 | ||
2408 | static 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 | |||
2437 | static 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 | |||
2044 | int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | 2461 | int 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)); | 2714 | skip_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 | } |