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 | <|||
