| @@ -2115,20 +2115,108 @@ static const char *ib_qp_type_str(enum ib_qp_type type) · 2114 unmodified lines |
| 2115 | 2115 | return "IB_QPT_RAW_PACKET"; |
| 2116 | 2116 | case MLX5_IB_QPT_REG_UMR: |
| 2117 | 2117 | return "MLX5_IB_QPT_REG_UMR"; |
| 2118 | + case IB_QPT_DRIVER: |
| 2119 | + return "IB_QPT_DRIVER"; |
| 2118 | 2120 | case IB_QPT_MAX: |
| 2119 | 2121 | default: |
| 2120 | 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 | 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 | 2212 | struct ib_udata *udata) |
| 2127 | 2213 | { |
| 2128 | 2214 | struct mlx5_ib_dev *dev; |
| 2129 | 2215 | struct mlx5_ib_qp *qp; |
| 2130 | 2216 | u16 xrcdn = 0; |
| 2131 | 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 | 2221 | if (pd) { |
| 2134 | 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 | 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 | 2254 | switch (init_attr->qp_type) { |
| 2157 | 2255 | case IB_QPT_XRC_TGT: |
| 2158 | 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 | 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 | 2318 | return &qp->ibqp; |
| 2218 | 2319 | } |
| 2219 | 2320 | |