| @@ -2115,20 +2115,108 @@ static const char *ib_qp_type_str(enum ib_qp_type type) · 2114 unmodified lines |
| 2115 | return "IB_QPT_RAW_PACKET"; | 2115 | return "IB_QPT_RAW_PACKET"; |
| 2116 | case MLX5_IB_QPT_REG_UMR: | 2116 | case MLX5_IB_QPT_REG_UMR: |
| 2117 | return "MLX5_IB_QPT_REG_UMR"; | 2117 | return "MLX5_IB_QPT_REG_UMR"; |
| | 2118 | case IB_QPT_DRIVER: |
| | 2119 | return "IB_QPT_DRIVER"; |
| 2118 | case IB_QPT_MAX: | 2120 | case IB_QPT_MAX: |
| 2119 | default: | 2121 | default: |
| 2120 | return "Invalid QP type"; | 2122 | return "Invalid QP type"; |
| 2121 | } | 2123 | } |
| 2122 | } | 2124 | } |
| 2123 | | 2125 | |
| | 2126 | static struct ib_qp *mlx5_ib_create_dct(struct ib_pd *pd, |
| | 2127 | struct ib_qp_init_attr *attr, |
| | 2128 | struct mlx5_ib_create_qp *ucmd) |
| | 2129 | { |
| | 2130 | struct mlx5_ib_dev *dev; |
| | 2131 | struct mlx5_ib_qp *qp; |
| | 2132 | int err = 0; |
| | 2133 | u32 uidx = MLX5_IB_DEFAULT_UIDX; |
| | 2134 | void *dctc; |
| | 2135 | |
| | 2136 | if (!attr->srq || !attr->recv_cq) |
| | 2137 | return ERR_PTR(-EINVAL); |
| | 2138 | |
| | 2139 | dev = to_mdev(pd->device); |
| | 2140 | |
| | 2141 | err = get_qp_user_index(to_mucontext(pd->uobject->context), |
| | 2142 | ucmd, sizeof(*ucmd), &uidx); |
| | 2143 | if (err) |
| | 2144 | return ERR_PTR(err); |
| | 2145 | |
| | 2146 | qp = kzalloc(sizeof(*qp), GFP_KERNEL); |
| | 2147 | if (!qp) |
| | 2148 | return ERR_PTR(-ENOMEM); |
| | 2149 | |
| | 2150 | qp->dct.in = kzalloc(MLX5_ST_SZ_BYTES(create_dct_in), GFP_KERNEL); |
| | 2151 | if (!qp->dct.in) { |
| | 2152 | err = -ENOMEM; |
| | 2153 | goto err_free; |
| | 2154 | } |
| | 2155 | |
| | 2156 | dctc = MLX5_ADDR_OF(create_dct_in, qp->dct.in, dct_context_entry); |
| | 2157 | qp->driver_qp_type = MLX5_IB_QPT_DCT; |
| | 2158 | MLX5_SET(dctc, dctc, pd, to_mpd(pd)->pdn); |
| | 2159 | MLX5_SET(dctc, dctc, srqn_xrqn, to_msrq(attr->srq)->msrq.srqn); |
| | 2160 | MLX5_SET(dctc, dctc, cqn, to_mcq(attr->recv_cq)->mcq.cqn); |
| | 2161 | MLX5_SET64(dctc, dctc, dc_access_key, ucmd->access_key); |
| | 2162 | MLX5_SET(dctc, dctc, user_index, uidx); |
| | 2163 | |
| | 2164 | qp->state = IB_QPS_RESET; |
| | 2165 | |
| | 2166 | return &qp->ibqp; |
| | 2167 | err_free: |
| | 2168 | kfree(qp); |
| | 2169 | return ERR_PTR(err); |
| | 2170 | } |
| | 2171 | |
| | 2172 | static int set_mlx_qp_type(struct mlx5_ib_dev *dev, |
| | 2173 | struct ib_qp_init_attr *init_attr, |
| | 2174 | struct mlx5_ib_create_qp *ucmd, |
| | 2175 | struct ib_udata *udata) |
| | 2176 | { |
| | 2177 | enum { MLX_QP_FLAGS = MLX5_QP_FLAG_TYPE_DCT | MLX5_QP_FLAG_TYPE_DCI }; |
| | 2178 | int err; |
| | 2179 | |
| | 2180 | if (!udata) |
| | 2181 | return -EINVAL; |
| | 2182 | |
| | 2183 | if (udata->inlen < sizeof(*ucmd)) { |
| | 2184 | mlx5_ib_dbg(dev, "create_qp user command is smaller than expected\n"); |
| | 2185 | return -EINVAL; |
| | 2186 | } |
| | 2187 | err = ib_copy_from_udata(ucmd, udata, sizeof(*ucmd)); |
| | 2188 | if (err) |
| | 2189 | return err; |
| | 2190 | |
| | 2191 | if ((ucmd->flags & MLX_QP_FLAGS) == MLX5_QP_FLAG_TYPE_DCI) { |
| | 2192 | init_attr->qp_type = MLX5_IB_QPT_DCI; |
| | 2193 | } else { |
| | 2194 | if ((ucmd->flags & MLX_QP_FLAGS) == MLX5_QP_FLAG_TYPE_DCT) { |
| | 2195 | init_attr->qp_type = MLX5_IB_QPT_DCT; |
| | 2196 | } else { |
| | 2197 | mlx5_ib_dbg(dev, "Invalid QP flags\n"); |
| | 2198 | return -EINVAL; |
| | 2199 | } |
| | 2200 | } |
| | 2201 | |
| | 2202 | if (!MLX5_CAP_GEN(dev->mdev, dct)) { |
| | 2203 | mlx5_ib_dbg(dev, "DC transport is not supported\n"); |
| | 2204 | return -EOPNOTSUPP; |
| | 2205 | } |
| | 2206 | |
| | 2207 | return 0; |
| | 2208 | } |
| | 2209 | |
| 2124 | struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, | 2210 | struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, |
| 2125 | struct ib_qp_init_attr *init_attr, | 2211 | struct ib_qp_init_attr *verbs_init_attr, |
| 2126 | struct ib_udata *udata) | 2212 | struct ib_udata *udata) |
| 2127 | { | 2213 | { |
| 2128 | struct mlx5_ib_dev *dev; | 2214 | struct mlx5_ib_dev *dev; |
| 2129 | struct mlx5_ib_qp *qp; | 2215 | struct mlx5_ib_qp *qp; |
| 2130 | u16 xrcdn = 0; | 2216 | u16 xrcdn = 0; |
| 2131 | int err; | 2217 | int err; |
| | 2218 | struct ib_qp_init_attr mlx_init_attr; |
| | 2219 | struct ib_qp_init_attr *init_attr = verbs_init_attr; |
| 2132 | | 2220 | |
| 2133 | if (pd) { | 2221 | if (pd) { |
| 2134 | dev = to_mdev(pd->device); | 2222 | dev = to_mdev(pd->device); |
| @@ -2153,6 +2241,16 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, · 18 unmodified lines |
| 2153 | dev = to_mdev(to_mxrcd(init_attr->xrcd)->ibxrcd.device); | 2241 | dev = to_mdev(to_mxrcd(init_attr->xrcd)->ibxrcd.device); |
| 2154 | } | 2242 | } |
| 2155 | | 2243 | |
| | 2244 | if (init_attr->qp_type == IB_QPT_DRIVER) { |
| | 2245 | struct mlx5_ib_create_qp ucmd; |
| | 2246 | |
| | 2247 | init_attr = &mlx_init_attr; |
| | 2248 | memcpy(init_attr, verbs_init_attr, sizeof(*verbs_init_attr)); |
| | 2249 | err = set_mlx_qp_type(dev, init_attr, &ucmd, udata); |
| | 2250 | if (err) |
| | 2251 | return ERR_PTR(err); |
| | 2252 | } |
| | 2253 | |
| 2156 | switch (init_attr->qp_type) { | 2254 | switch (init_attr->qp_type) { |
| 2157 | case IB_QPT_XRC_TGT: | 2255 | case IB_QPT_XRC_TGT: |
| 2158 | case IB_QPT_XRC_INI: | 2256 | case IB_QPT_XRC_INI: |
| @@ -2214,6 +2312,9 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, · 55 unmodified lines |
| 2214 | return ERR_PTR(-EINVAL); | 2312 | return ERR_PTR(-EINVAL); |
| 2215 | } | 2313 | } |
| 2216 | | 2314 | |
| | 2315 | if (verbs_init_attr->qp_type == IB_QPT_DRIVER) |
| | 2316 | qp->qp_sub_type = init_attr->qp_type; |
| | 2317 | |
| 2217 | return &qp->ibqp; | 2318 | return &qp->ibqp; |
| 2218 | } | 2319 | } |
| 2219 | | 2320 | |