aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSagi Grimberg <sagig@mellanox.com>2014-02-23 07:19:11 -0500
committerRoland Dreier <roland@purestorage.com>2014-03-07 14:39:51 -0500
commite6631814fb3ac454fbbf47ea343c2b9508e4e1ba (patch)
treedfe554c9fbe5f3f4f0a37276a74180bf2f4e9fd2
parent3bcdb17a5e88288ead90be3c107e754a6075a5b0 (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.c422
-rw-r--r--include/linux/mlx5/qp.h61
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
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_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
1780static void set_frwr_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr, 1800static 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
1984static 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
1994static 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
2006static 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
2058static 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
2109static 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