1 /*-
2 * Copyright (c) 2016-2020, Mellanox Technologies, Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 *
25 * $FreeBSD$
26 */
27
28 #include "opt_rss.h"
29 #include "opt_ratelimit.h"
30
31 #include <dev/mlx5/mlx5_ib/mlx5_ib.h>
32
33 struct mlx5_ib_gsi_wr {
34 struct ib_cqe cqe;
35 struct ib_wc wc;
36 int send_flags;
37 bool completed:1;
38 };
39
40 struct mlx5_ib_gsi_qp {
41 struct ib_qp ibqp;
42 struct ib_qp *rx_qp;
43 u8 port_num;
44 struct ib_qp_cap cap;
45 enum ib_sig_type sq_sig_type;
46 /* Serialize qp state modifications */
47 struct mutex mutex;
48 struct ib_cq *cq;
49 struct mlx5_ib_gsi_wr *outstanding_wrs;
50 u32 outstanding_pi, outstanding_ci;
51 int num_qps;
52 /* Protects access to the tx_qps. Post send operations synchronize
53 * with tx_qp creation in setup_qp(). Also protects the
54 * outstanding_wrs array and indices.
55 */
56 spinlock_t lock;
57 struct ib_qp **tx_qps;
58 };
59
60 static struct mlx5_ib_gsi_qp *gsi_qp(struct ib_qp *qp)
61 {
62 return container_of(qp, struct mlx5_ib_gsi_qp, ibqp);
63 }
64
65 static bool mlx5_ib_deth_sqpn_cap(struct mlx5_ib_dev *dev)
66 {
67 return MLX5_CAP_GEN(dev->mdev, set_deth_sqpn);
68 }
69
70 /* Call with gsi->lock locked */
71 static void generate_completions(struct mlx5_ib_gsi_qp *gsi)
72 {
73 struct ib_cq *gsi_cq = gsi->ibqp.send_cq;
74 struct mlx5_ib_gsi_wr *wr;
75 u32 index;
76
77 for (index = gsi->outstanding_ci; index != gsi->outstanding_pi;
78 index++) {
79 wr = &gsi->outstanding_wrs[index % gsi->cap.max_send_wr];
80
81 if (!wr->completed)
82 break;
83
84 if (gsi->sq_sig_type == IB_SIGNAL_ALL_WR ||
85 wr->send_flags & IB_SEND_SIGNALED)
86 WARN_ON_ONCE(mlx5_ib_generate_wc(gsi_cq, &wr->wc));
87
88 wr->completed = false;
89 }
90
91 gsi->outstanding_ci = index;
92 }
93
94 static void handle_single_completion(struct ib_cq *cq, struct ib_wc *wc)
95 {
96 struct mlx5_ib_gsi_qp *gsi = cq->cq_context;
97 struct mlx5_ib_gsi_wr *wr =
98 container_of(wc->wr_cqe, struct mlx5_ib_gsi_wr, cqe);
99 u64 wr_id;
100 unsigned long flags;
101
102 spin_lock_irqsave(&gsi->lock, flags);
103 wr->completed = true;
104 wr_id = wr->wc.wr_id;
105 wr->wc = *wc;
106 wr->wc.wr_id = wr_id;
107 wr->wc.qp = &gsi->ibqp;
108
109 generate_completions(gsi);
110 spin_unlock_irqrestore(&gsi->lock, flags);
111 }
112
113 struct ib_qp *mlx5_ib_gsi_create_qp(struct ib_pd *pd,
114 struct ib_qp_init_attr *init_attr)
115 {
116 struct mlx5_ib_dev *dev = to_mdev(pd->device);
117 struct mlx5_ib_gsi_qp *gsi;
118 struct ib_qp_init_attr hw_init_attr = *init_attr;
119 const u8 port_num = init_attr->port_num;
120 const int num_pkeys = pd->device->attrs.max_pkeys;
121 const int num_qps = mlx5_ib_deth_sqpn_cap(dev) ? num_pkeys : 0;
122 int ret;
123
124 mlx5_ib_dbg(dev, "creating GSI QP\n");
125
126 if (port_num > ARRAY_SIZE(dev->devr.ports) || port_num < 1) {
127 mlx5_ib_warn(dev,
128 "invalid port number %d during GSI QP creation\n",
129 port_num);
130 return ERR_PTR(-EINVAL);
131 }
132
133 gsi = kzalloc(sizeof(*gsi), GFP_KERNEL);
134 if (!gsi)
135 return ERR_PTR(-ENOMEM);
136
137 gsi->tx_qps = kcalloc(num_qps, sizeof(*gsi->tx_qps), GFP_KERNEL);
138 if (!gsi->tx_qps) {
139 ret = -ENOMEM;
140 goto err_free;
141 }
142
143 gsi->outstanding_wrs = kcalloc(init_attr->cap.max_send_wr,
144 sizeof(*gsi->outstanding_wrs),
145 GFP_KERNEL);
146 if (!gsi->outstanding_wrs) {
147 ret = -ENOMEM;
148 goto err_free_tx;
149 }
150
151 mutex_init(&gsi->mutex);
152
153 mutex_lock(&dev->devr.mutex);
154
155 if (dev->devr.ports[port_num - 1].gsi) {
156 mlx5_ib_warn(dev, "GSI QP already exists on port %d\n",
157 port_num);
158 ret = -EBUSY;
159 goto err_free_wrs;
160 }
161 gsi->num_qps = num_qps;
162 spin_lock_init(&gsi->lock);
163
164 gsi->cap = init_attr->cap;
165 gsi->sq_sig_type = init_attr->sq_sig_type;
166 gsi->ibqp.qp_num = 1;
167 gsi->port_num = port_num;
168
169 gsi->cq = ib_alloc_cq(pd->device, gsi, init_attr->cap.max_send_wr, 0,
170 IB_POLL_SOFTIRQ);
171 if (IS_ERR(gsi->cq)) {
172 mlx5_ib_warn(dev, "unable to create send CQ for GSI QP. error %ld\n",
173 PTR_ERR(gsi->cq));
174 ret = PTR_ERR(gsi->cq);
175 goto err_free_wrs;
176 }
177
178 hw_init_attr.qp_type = MLX5_IB_QPT_HW_GSI;
179 hw_init_attr.send_cq = gsi->cq;
180 if (num_qps) {
181 hw_init_attr.cap.max_send_wr = 0;
182 hw_init_attr.cap.max_send_sge = 0;
183 hw_init_attr.cap.max_inline_data = 0;
184 }
185 gsi->rx_qp = ib_create_qp(pd, &hw_init_attr);
186 if (IS_ERR(gsi->rx_qp)) {
187 mlx5_ib_warn(dev, "unable to create hardware GSI QP. error %ld\n",
188 PTR_ERR(gsi->rx_qp));
189 ret = PTR_ERR(gsi->rx_qp);
190 goto err_destroy_cq;
191 }
192
193 dev->devr.ports[init_attr->port_num - 1].gsi = gsi;
194
195 mutex_unlock(&dev->devr.mutex);
196
197 return &gsi->ibqp;
198
199 err_destroy_cq:
200 ib_free_cq(gsi->cq);
201 err_free_wrs:
202 mutex_unlock(&dev->devr.mutex);
203 kfree(gsi->outstanding_wrs);
204 err_free_tx:
205 kfree(gsi->tx_qps);
206 err_free:
207 kfree(gsi);
208 return ERR_PTR(ret);
209 }
210
211 int mlx5_ib_gsi_destroy_qp(struct ib_qp *qp)
212 {
213 struct mlx5_ib_dev *dev = to_mdev(qp->device);
214 struct mlx5_ib_gsi_qp *gsi = gsi_qp(qp);
215 const int port_num = gsi->port_num;
216 int qp_index;
217 int ret;
218
219 mlx5_ib_dbg(dev, "destroying GSI QP\n");
220
221 mutex_lock(&dev->devr.mutex);
222 ret = ib_destroy_qp(gsi->rx_qp);
223 if (ret) {
224 mlx5_ib_warn(dev, "unable to destroy hardware GSI QP. error %d\n",
225 ret);
226 mutex_unlock(&dev->devr.mutex);
227 return ret;
228 }
229 dev->devr.ports[port_num - 1].gsi = NULL;
230 mutex_unlock(&dev->devr.mutex);
231 gsi->rx_qp = NULL;
232
233 for (qp_index = 0; qp_index < gsi->num_qps; ++qp_index) {
234 if (!gsi->tx_qps[qp_index])
235 continue;
236 WARN_ON_ONCE(ib_destroy_qp(gsi->tx_qps[qp_index]));
237 gsi->tx_qps[qp_index] = NULL;
238 }
239
240 ib_free_cq(gsi->cq);
241
242 kfree(gsi->outstanding_wrs);
243 kfree(gsi->tx_qps);
244 kfree(gsi);
245
246 return 0;
247 }
248
249 static struct ib_qp *create_gsi_ud_qp(struct mlx5_ib_gsi_qp *gsi)
250 {
251 struct ib_pd *pd = gsi->rx_qp->pd;
252 struct ib_qp_init_attr init_attr = {
253 .event_handler = gsi->rx_qp->event_handler,
254 .qp_context = gsi->rx_qp->qp_context,
255 .send_cq = gsi->cq,
256 .recv_cq = gsi->rx_qp->recv_cq,
257 .cap = {
258 .max_send_wr = gsi->cap.max_send_wr,
259 .max_send_sge = gsi->cap.max_send_sge,
260 .max_inline_data = gsi->cap.max_inline_data,
261 },
262 .sq_sig_type = gsi->sq_sig_type,
263 .qp_type = IB_QPT_UD,
264 .create_flags = MLX5_IB_QP_CREATE_SQPN_QP1,
265 };
266
267 return ib_create_qp(pd, &init_attr);
268 }
269
270 static int modify_to_rts(struct mlx5_ib_gsi_qp *gsi, struct ib_qp *qp,
271 u16 qp_index)
272 {
273 struct mlx5_ib_dev *dev = to_mdev(qp->device);
274 struct ib_qp_attr attr;
275 int mask;
276 int ret;
277
278 mask = IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_QKEY | IB_QP_PORT;
279 attr.qp_state = IB_QPS_INIT;
280 attr.pkey_index = qp_index;
281 attr.qkey = IB_QP1_QKEY;
282 attr.port_num = gsi->port_num;
283 ret = ib_modify_qp(qp, &attr, mask);
284 if (ret) {
285 mlx5_ib_err(dev, "could not change QP%d state to INIT: %d\n",
286 qp->qp_num, ret);
287 return ret;
288 }
289
290 attr.qp_state = IB_QPS_RTR;
291 ret = ib_modify_qp(qp, &attr, IB_QP_STATE);
292 if (ret) {
293 mlx5_ib_err(dev, "could not change QP%d state to RTR: %d\n",
294 qp->qp_num, ret);
295 return ret;
296 }
297
298 attr.qp_state = IB_QPS_RTS;
299 attr.sq_psn = 0;
300 ret = ib_modify_qp(qp, &attr, IB_QP_STATE | IB_QP_SQ_PSN);
301 if (ret) {
302 mlx5_ib_err(dev, "could not change QP%d state to RTS: %d\n",
303 qp->qp_num, ret);
304 return ret;
305 }
306
307 return 0;
308 }
309
310 static void setup_qp(struct mlx5_ib_gsi_qp *gsi, u16 qp_index)
311 {
312 struct ib_device *device = gsi->rx_qp->device;
313 struct mlx5_ib_dev *dev = to_mdev(device);
314 struct ib_qp *qp;
315 unsigned long flags;
316 u16 pkey;
317 int ret;
318
319 ret = ib_query_pkey(device, gsi->port_num, qp_index, &pkey);
320 if (ret) {
321 mlx5_ib_warn(dev, "unable to read P_Key at port %d, index %d\n",
322 gsi->port_num, qp_index);
323 return;
324 }
325
326 if (!pkey) {
327 mlx5_ib_dbg(dev, "invalid P_Key at port %d, index %d. Skipping.\n",
328 gsi->port_num, qp_index);
329 return;
330 }
331
332 spin_lock_irqsave(&gsi->lock, flags);
333 qp = gsi->tx_qps[qp_index];
334 spin_unlock_irqrestore(&gsi->lock, flags);
335 if (qp) {
336 mlx5_ib_dbg(dev, "already existing GSI TX QP at port %d, index %d. Skipping\n",
337 gsi->port_num, qp_index);
338 return;
339 }
340
341 qp = create_gsi_ud_qp(gsi);
342 if (IS_ERR(qp)) {
343 mlx5_ib_warn(dev, "unable to create hardware UD QP for GSI: %ld\n",
344 PTR_ERR(qp));
345 return;
346 }
347
348 ret = modify_to_rts(gsi, qp, qp_index);
349 if (ret)
350 goto err_destroy_qp;
351
352 spin_lock_irqsave(&gsi->lock, flags);
353 WARN_ON_ONCE(gsi->tx_qps[qp_index]);
354 gsi->tx_qps[qp_index] = qp;
355 spin_unlock_irqrestore(&gsi->lock, flags);
356
357 return;
358
359 err_destroy_qp:
360 WARN_ON_ONCE(qp);
361 }
362
363 static void setup_qps(struct mlx5_ib_gsi_qp *gsi)
364 {
365 u16 qp_index;
366
367 for (qp_index = 0; qp_index < gsi->num_qps; ++qp_index)
368 setup_qp(gsi, qp_index);
369 }
370
371 int mlx5_ib_gsi_modify_qp(struct ib_qp *qp, struct ib_qp_attr *attr,
372 int attr_mask)
373 {
374 struct mlx5_ib_dev *dev = to_mdev(qp->device);
375 struct mlx5_ib_gsi_qp *gsi = gsi_qp(qp);
376 int ret;
377
378 mlx5_ib_dbg(dev, "modifying GSI QP to state %d\n", attr->qp_state);
379
380 mutex_lock(&gsi->mutex);
381 ret = ib_modify_qp(gsi->rx_qp, attr, attr_mask);
382 if (ret) {
383 mlx5_ib_warn(dev, "unable to modify GSI rx QP: %d\n", ret);
384 goto unlock;
385 }
386
387 if (to_mqp(gsi->rx_qp)->state == IB_QPS_RTS)
388 setup_qps(gsi);
389
390 unlock:
391 mutex_unlock(&gsi->mutex);
392
393 return ret;
394 }
395
396 int mlx5_ib_gsi_query_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
397 int qp_attr_mask,
398 struct ib_qp_init_attr *qp_init_attr)
399 {
400 struct mlx5_ib_gsi_qp *gsi = gsi_qp(qp);
401 int ret;
402
403 mutex_lock(&gsi->mutex);
404 ret = ib_query_qp(gsi->rx_qp, qp_attr, qp_attr_mask, qp_init_attr);
405 qp_init_attr->cap = gsi->cap;
406 mutex_unlock(&gsi->mutex);
407
408 return ret;
409 }
410
411 /* Call with gsi->lock locked */
412 static int mlx5_ib_add_outstanding_wr(struct mlx5_ib_gsi_qp *gsi,
413 struct ib_ud_wr *wr, struct ib_wc *wc)
414 {
415 struct mlx5_ib_dev *dev = to_mdev(gsi->rx_qp->device);
416 struct mlx5_ib_gsi_wr *gsi_wr;
417
418 if (gsi->outstanding_pi == gsi->outstanding_ci + gsi->cap.max_send_wr) {
419 mlx5_ib_warn(dev, "no available GSI work request.\n");
420 return -ENOMEM;
421 }
422
423 gsi_wr = &gsi->outstanding_wrs[gsi->outstanding_pi %
424 gsi->cap.max_send_wr];
425 gsi->outstanding_pi++;
426
427 if (!wc) {
428 memset(&gsi_wr->wc, 0, sizeof(gsi_wr->wc));
429 gsi_wr->wc.pkey_index = wr->pkey_index;
430 gsi_wr->wc.wr_id = wr->wr.wr_id;
431 } else {
432 gsi_wr->wc = *wc;
433 gsi_wr->completed = true;
434 }
435
436 gsi_wr->cqe.done = &handle_single_completion;
437 wr->wr.wr_cqe = &gsi_wr->cqe;
438
439 return 0;
440 }
441
442 /* Call with gsi->lock locked */
443 static int mlx5_ib_gsi_silent_drop(struct mlx5_ib_gsi_qp *gsi,
444 struct ib_ud_wr *wr)
445 {
446 struct ib_wc wc = {
447 { .wr_id = wr->wr.wr_id },
448 .status = IB_WC_SUCCESS,
449 .opcode = IB_WC_SEND,
450 .qp = &gsi->ibqp,
451 };
452 int ret;
453
454 ret = mlx5_ib_add_outstanding_wr(gsi, wr, &wc);
455 if (ret)
456 return ret;
457
458 generate_completions(gsi);
459
460 return 0;
461 }
462
463 /* Call with gsi->lock locked */
464 static struct ib_qp *get_tx_qp(struct mlx5_ib_gsi_qp *gsi, struct ib_ud_wr *wr)
465 {
466 struct mlx5_ib_dev *dev = to_mdev(gsi->rx_qp->device);
467 int qp_index = wr->pkey_index;
468
469 if (!mlx5_ib_deth_sqpn_cap(dev))
470 return gsi->rx_qp;
471
472 if (qp_index >= gsi->num_qps)
473 return NULL;
474
475 return gsi->tx_qps[qp_index];
476 }
477
478 int mlx5_ib_gsi_post_send(struct ib_qp *qp, const struct ib_send_wr *wr,
479 const struct ib_send_wr **bad_wr)
480 {
481 struct mlx5_ib_gsi_qp *gsi = gsi_qp(qp);
482 struct ib_qp *tx_qp;
483 unsigned long flags;
484 int ret;
485
486 for (; wr; wr = wr->next) {
487 struct ib_ud_wr cur_wr = *ud_wr(wr);
488
489 cur_wr.wr.next = NULL;
490
491 spin_lock_irqsave(&gsi->lock, flags);
492 tx_qp = get_tx_qp(gsi, &cur_wr);
493 if (!tx_qp) {
494 ret = mlx5_ib_gsi_silent_drop(gsi, &cur_wr);
495 if (ret)
496 goto err;
497 spin_unlock_irqrestore(&gsi->lock, flags);
498 continue;
499 }
500
501 ret = mlx5_ib_add_outstanding_wr(gsi, &cur_wr, NULL);
502 if (ret)
503 goto err;
504
505 ret = ib_post_send(tx_qp, &cur_wr.wr, bad_wr);
506 if (ret) {
507 /* Undo the effect of adding the outstanding wr */
508 gsi->outstanding_pi = (gsi->outstanding_pi - 1) %
509 gsi->cap.max_send_wr;
510 goto err;
511 }
512 spin_unlock_irqrestore(&gsi->lock, flags);
513 }
514
515 return 0;
516
517 err:
518 spin_unlock_irqrestore(&gsi->lock, flags);
519 *bad_wr = wr;
520 return ret;
521 }
522
523 int mlx5_ib_gsi_post_recv(struct ib_qp *qp, const struct ib_recv_wr *wr,
524 const struct ib_recv_wr **bad_wr)
525 {
526 struct mlx5_ib_gsi_qp *gsi = gsi_qp(qp);
527
528 return ib_post_recv(gsi->rx_qp, wr, bad_wr);
529 }
530
531 void mlx5_ib_gsi_pkey_change(struct mlx5_ib_gsi_qp *gsi)
532 {
533 if (!gsi)
534 return;
535
536 mutex_lock(&gsi->mutex);
537 setup_qps(gsi);
538 mutex_unlock(&gsi->mutex);
539 }
Cache object: 0521682d4dec6d0eae12383153cb151f
|