2 * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35 struct mlx5_ib_gsi_wr
{
41 static bool mlx5_ib_deth_sqpn_cap(struct mlx5_ib_dev
*dev
)
43 return MLX5_CAP_GEN(dev
->mdev
, set_deth_sqpn
);
46 /* Call with gsi->lock locked */
47 static void generate_completions(struct mlx5_ib_qp
*mqp
)
49 struct mlx5_ib_gsi_qp
*gsi
= &mqp
->gsi
;
50 struct ib_cq
*gsi_cq
= mqp
->ibqp
.send_cq
;
51 struct mlx5_ib_gsi_wr
*wr
;
54 for (index
= gsi
->outstanding_ci
; index
!= gsi
->outstanding_pi
;
56 wr
= &gsi
->outstanding_wrs
[index
% gsi
->cap
.max_send_wr
];
61 WARN_ON_ONCE(mlx5_ib_generate_wc(gsi_cq
, &wr
->wc
));
62 wr
->completed
= false;
65 gsi
->outstanding_ci
= index
;
68 static void handle_single_completion(struct ib_cq
*cq
, struct ib_wc
*wc
)
70 struct mlx5_ib_gsi_qp
*gsi
= cq
->cq_context
;
71 struct mlx5_ib_gsi_wr
*wr
=
72 container_of(wc
->wr_cqe
, struct mlx5_ib_gsi_wr
, cqe
);
73 struct mlx5_ib_qp
*mqp
= container_of(gsi
, struct mlx5_ib_qp
, gsi
);
77 spin_lock_irqsave(&gsi
->lock
, flags
);
82 wr
->wc
.qp
= &mqp
->ibqp
;
84 generate_completions(mqp
);
85 spin_unlock_irqrestore(&gsi
->lock
, flags
);
88 int mlx5_ib_create_gsi(struct ib_pd
*pd
, struct mlx5_ib_qp
*mqp
,
89 struct ib_qp_init_attr
*attr
)
91 struct mlx5_ib_dev
*dev
= to_mdev(pd
->device
);
92 struct mlx5_ib_gsi_qp
*gsi
;
93 struct ib_qp_init_attr hw_init_attr
= *attr
;
94 const u8 port_num
= attr
->port_num
;
98 if (mlx5_ib_deth_sqpn_cap(dev
)) {
99 if (MLX5_CAP_GEN(dev
->mdev
,
100 port_type
) == MLX5_CAP_PORT_TYPE_IB
)
101 num_qps
= pd
->device
->attrs
.max_pkeys
;
102 else if (dev
->lag_active
)
103 num_qps
= MLX5_MAX_PORTS
;
107 gsi
->tx_qps
= kcalloc(num_qps
, sizeof(*gsi
->tx_qps
), GFP_KERNEL
);
111 gsi
->outstanding_wrs
=
112 kcalloc(attr
->cap
.max_send_wr
, sizeof(*gsi
->outstanding_wrs
),
114 if (!gsi
->outstanding_wrs
) {
119 mutex_lock(&dev
->devr
.mutex
);
121 if (dev
->devr
.ports
[port_num
- 1].gsi
) {
122 mlx5_ib_warn(dev
, "GSI QP already exists on port %d\n",
127 gsi
->num_qps
= num_qps
;
128 spin_lock_init(&gsi
->lock
);
130 gsi
->cap
= attr
->cap
;
131 gsi
->port_num
= port_num
;
133 gsi
->cq
= ib_alloc_cq(pd
->device
, gsi
, attr
->cap
.max_send_wr
, 0,
135 if (IS_ERR(gsi
->cq
)) {
136 mlx5_ib_warn(dev
, "unable to create send CQ for GSI QP. error %ld\n",
138 ret
= PTR_ERR(gsi
->cq
);
142 hw_init_attr
.qp_type
= MLX5_IB_QPT_HW_GSI
;
143 hw_init_attr
.send_cq
= gsi
->cq
;
145 hw_init_attr
.cap
.max_send_wr
= 0;
146 hw_init_attr
.cap
.max_send_sge
= 0;
147 hw_init_attr
.cap
.max_inline_data
= 0;
150 gsi
->rx_qp
= mlx5_ib_create_qp(pd
, &hw_init_attr
, NULL
);
151 if (IS_ERR(gsi
->rx_qp
)) {
152 mlx5_ib_warn(dev
, "unable to create hardware GSI QP. error %ld\n",
153 PTR_ERR(gsi
->rx_qp
));
154 ret
= PTR_ERR(gsi
->rx_qp
);
157 gsi
->rx_qp
->device
= pd
->device
;
159 gsi
->rx_qp
->real_qp
= gsi
->rx_qp
;
161 gsi
->rx_qp
->qp_type
= hw_init_attr
.qp_type
;
162 gsi
->rx_qp
->send_cq
= hw_init_attr
.send_cq
;
163 gsi
->rx_qp
->recv_cq
= hw_init_attr
.recv_cq
;
164 gsi
->rx_qp
->event_handler
= hw_init_attr
.event_handler
;
165 spin_lock_init(&gsi
->rx_qp
->mr_lock
);
166 INIT_LIST_HEAD(&gsi
->rx_qp
->rdma_mrs
);
167 INIT_LIST_HEAD(&gsi
->rx_qp
->sig_mrs
);
169 dev
->devr
.ports
[attr
->port_num
- 1].gsi
= gsi
;
171 mutex_unlock(&dev
->devr
.mutex
);
178 mutex_unlock(&dev
->devr
.mutex
);
179 kfree(gsi
->outstanding_wrs
);
185 int mlx5_ib_destroy_gsi(struct mlx5_ib_qp
*mqp
)
187 struct mlx5_ib_dev
*dev
= to_mdev(mqp
->ibqp
.device
);
188 struct mlx5_ib_gsi_qp
*gsi
= &mqp
->gsi
;
189 const int port_num
= gsi
->port_num
;
193 mutex_lock(&dev
->devr
.mutex
);
194 ret
= mlx5_ib_destroy_qp(gsi
->rx_qp
, NULL
);
196 mlx5_ib_warn(dev
, "unable to destroy hardware GSI QP. error %d\n",
198 mutex_unlock(&dev
->devr
.mutex
);
201 dev
->devr
.ports
[port_num
- 1].gsi
= NULL
;
202 mutex_unlock(&dev
->devr
.mutex
);
205 for (qp_index
= 0; qp_index
< gsi
->num_qps
; ++qp_index
) {
206 if (!gsi
->tx_qps
[qp_index
])
208 WARN_ON_ONCE(ib_destroy_qp(gsi
->tx_qps
[qp_index
]));
209 gsi
->tx_qps
[qp_index
] = NULL
;
214 kfree(gsi
->outstanding_wrs
);
221 static struct ib_qp
*create_gsi_ud_qp(struct mlx5_ib_gsi_qp
*gsi
)
223 struct ib_pd
*pd
= gsi
->rx_qp
->pd
;
224 struct ib_qp_init_attr init_attr
= {
225 .event_handler
= gsi
->rx_qp
->event_handler
,
226 .qp_context
= gsi
->rx_qp
->qp_context
,
228 .recv_cq
= gsi
->rx_qp
->recv_cq
,
230 .max_send_wr
= gsi
->cap
.max_send_wr
,
231 .max_send_sge
= gsi
->cap
.max_send_sge
,
232 .max_inline_data
= gsi
->cap
.max_inline_data
,
234 .qp_type
= IB_QPT_UD
,
235 .create_flags
= MLX5_IB_QP_CREATE_SQPN_QP1
,
238 return ib_create_qp(pd
, &init_attr
);
241 static int modify_to_rts(struct mlx5_ib_gsi_qp
*gsi
, struct ib_qp
*qp
,
244 struct mlx5_ib_dev
*dev
= to_mdev(qp
->device
);
245 struct ib_qp_attr attr
;
249 mask
= IB_QP_STATE
| IB_QP_PKEY_INDEX
| IB_QP_QKEY
| IB_QP_PORT
;
250 attr
.qp_state
= IB_QPS_INIT
;
251 attr
.pkey_index
= pkey_index
;
252 attr
.qkey
= IB_QP1_QKEY
;
253 attr
.port_num
= gsi
->port_num
;
254 ret
= ib_modify_qp(qp
, &attr
, mask
);
256 mlx5_ib_err(dev
, "could not change QP%d state to INIT: %d\n",
261 attr
.qp_state
= IB_QPS_RTR
;
262 ret
= ib_modify_qp(qp
, &attr
, IB_QP_STATE
);
264 mlx5_ib_err(dev
, "could not change QP%d state to RTR: %d\n",
269 attr
.qp_state
= IB_QPS_RTS
;
271 ret
= ib_modify_qp(qp
, &attr
, IB_QP_STATE
| IB_QP_SQ_PSN
);
273 mlx5_ib_err(dev
, "could not change QP%d state to RTS: %d\n",
281 static void setup_qp(struct mlx5_ib_gsi_qp
*gsi
, u16 qp_index
)
283 struct ib_device
*device
= gsi
->rx_qp
->device
;
284 struct mlx5_ib_dev
*dev
= to_mdev(device
);
285 int pkey_index
= qp_index
;
286 struct mlx5_ib_qp
*mqp
;
292 if (MLX5_CAP_GEN(dev
->mdev
, port_type
) != MLX5_CAP_PORT_TYPE_IB
)
295 ret
= ib_query_pkey(device
, gsi
->port_num
, pkey_index
, &pkey
);
297 mlx5_ib_warn(dev
, "unable to read P_Key at port %d, index %d\n",
298 gsi
->port_num
, qp_index
);
303 mlx5_ib_dbg(dev
, "invalid P_Key at port %d, index %d. Skipping.\n",
304 gsi
->port_num
, qp_index
);
308 spin_lock_irqsave(&gsi
->lock
, flags
);
309 qp
= gsi
->tx_qps
[qp_index
];
310 spin_unlock_irqrestore(&gsi
->lock
, flags
);
312 mlx5_ib_dbg(dev
, "already existing GSI TX QP at port %d, index %d. Skipping\n",
313 gsi
->port_num
, qp_index
);
317 qp
= create_gsi_ud_qp(gsi
);
319 mlx5_ib_warn(dev
, "unable to create hardware UD QP for GSI: %ld\n",
326 mqp
->gsi_lag_port
= qp_index
+ 1;
327 ret
= modify_to_rts(gsi
, qp
, pkey_index
);
331 spin_lock_irqsave(&gsi
->lock
, flags
);
332 WARN_ON_ONCE(gsi
->tx_qps
[qp_index
]);
333 gsi
->tx_qps
[qp_index
] = qp
;
334 spin_unlock_irqrestore(&gsi
->lock
, flags
);
342 static void setup_qps(struct mlx5_ib_gsi_qp
*gsi
)
344 struct mlx5_ib_dev
*dev
= to_mdev(gsi
->rx_qp
->device
);
347 mutex_lock(&dev
->devr
.mutex
);
348 for (qp_index
= 0; qp_index
< gsi
->num_qps
; ++qp_index
)
349 setup_qp(gsi
, qp_index
);
350 mutex_unlock(&dev
->devr
.mutex
);
353 int mlx5_ib_gsi_modify_qp(struct ib_qp
*qp
, struct ib_qp_attr
*attr
,
356 struct mlx5_ib_dev
*dev
= to_mdev(qp
->device
);
357 struct mlx5_ib_qp
*mqp
= to_mqp(qp
);
358 struct mlx5_ib_gsi_qp
*gsi
= &mqp
->gsi
;
361 mlx5_ib_dbg(dev
, "modifying GSI QP to state %d\n", attr
->qp_state
);
363 ret
= ib_modify_qp(gsi
->rx_qp
, attr
, attr_mask
);
365 mlx5_ib_warn(dev
, "unable to modify GSI rx QP: %d\n", ret
);
369 if (to_mqp(gsi
->rx_qp
)->state
== IB_QPS_RTS
)
374 int mlx5_ib_gsi_query_qp(struct ib_qp
*qp
, struct ib_qp_attr
*qp_attr
,
376 struct ib_qp_init_attr
*qp_init_attr
)
378 struct mlx5_ib_qp
*mqp
= to_mqp(qp
);
379 struct mlx5_ib_gsi_qp
*gsi
= &mqp
->gsi
;
382 ret
= ib_query_qp(gsi
->rx_qp
, qp_attr
, qp_attr_mask
, qp_init_attr
);
383 qp_init_attr
->cap
= gsi
->cap
;
387 /* Call with gsi->lock locked */
388 static int mlx5_ib_add_outstanding_wr(struct mlx5_ib_qp
*mqp
,
389 struct ib_ud_wr
*wr
, struct ib_wc
*wc
)
391 struct mlx5_ib_gsi_qp
*gsi
= &mqp
->gsi
;
392 struct mlx5_ib_dev
*dev
= to_mdev(gsi
->rx_qp
->device
);
393 struct mlx5_ib_gsi_wr
*gsi_wr
;
395 if (gsi
->outstanding_pi
== gsi
->outstanding_ci
+ gsi
->cap
.max_send_wr
) {
396 mlx5_ib_warn(dev
, "no available GSI work request.\n");
400 gsi_wr
= &gsi
->outstanding_wrs
[gsi
->outstanding_pi
%
401 gsi
->cap
.max_send_wr
];
402 gsi
->outstanding_pi
++;
405 memset(&gsi_wr
->wc
, 0, sizeof(gsi_wr
->wc
));
406 gsi_wr
->wc
.pkey_index
= wr
->pkey_index
;
407 gsi_wr
->wc
.wr_id
= wr
->wr
.wr_id
;
410 gsi_wr
->completed
= true;
413 gsi_wr
->cqe
.done
= &handle_single_completion
;
414 wr
->wr
.wr_cqe
= &gsi_wr
->cqe
;
419 /* Call with gsi->lock locked */
420 static int mlx5_ib_gsi_silent_drop(struct mlx5_ib_qp
*mqp
, struct ib_ud_wr
*wr
)
423 { .wr_id
= wr
->wr
.wr_id
},
424 .status
= IB_WC_SUCCESS
,
425 .opcode
= IB_WC_SEND
,
430 ret
= mlx5_ib_add_outstanding_wr(mqp
, wr
, &wc
);
434 generate_completions(mqp
);
439 /* Call with gsi->lock locked */
440 static struct ib_qp
*get_tx_qp(struct mlx5_ib_gsi_qp
*gsi
, struct ib_ud_wr
*wr
)
442 struct mlx5_ib_dev
*dev
= to_mdev(gsi
->rx_qp
->device
);
443 struct mlx5_ib_ah
*ah
= to_mah(wr
->ah
);
444 int qp_index
= wr
->pkey_index
;
449 if (dev
->lag_active
&& ah
->xmit_port
)
450 qp_index
= ah
->xmit_port
- 1;
452 if (qp_index
>= gsi
->num_qps
)
455 return gsi
->tx_qps
[qp_index
];
458 int mlx5_ib_gsi_post_send(struct ib_qp
*qp
, const struct ib_send_wr
*wr
,
459 const struct ib_send_wr
**bad_wr
)
461 struct mlx5_ib_qp
*mqp
= to_mqp(qp
);
462 struct mlx5_ib_gsi_qp
*gsi
= &mqp
->gsi
;
467 for (; wr
; wr
= wr
->next
) {
468 struct ib_ud_wr cur_wr
= *ud_wr(wr
);
470 cur_wr
.wr
.next
= NULL
;
472 spin_lock_irqsave(&gsi
->lock
, flags
);
473 tx_qp
= get_tx_qp(gsi
, &cur_wr
);
475 ret
= mlx5_ib_gsi_silent_drop(mqp
, &cur_wr
);
478 spin_unlock_irqrestore(&gsi
->lock
, flags
);
482 ret
= mlx5_ib_add_outstanding_wr(mqp
, &cur_wr
, NULL
);
486 ret
= ib_post_send(tx_qp
, &cur_wr
.wr
, bad_wr
);
488 /* Undo the effect of adding the outstanding wr */
489 gsi
->outstanding_pi
--;
492 spin_unlock_irqrestore(&gsi
->lock
, flags
);
498 spin_unlock_irqrestore(&gsi
->lock
, flags
);
503 int mlx5_ib_gsi_post_recv(struct ib_qp
*qp
, const struct ib_recv_wr
*wr
,
504 const struct ib_recv_wr
**bad_wr
)
506 struct mlx5_ib_qp
*mqp
= to_mqp(qp
);
507 struct mlx5_ib_gsi_qp
*gsi
= &mqp
->gsi
;
509 return ib_post_recv(gsi
->rx_qp
, wr
, bad_wr
);
512 void mlx5_ib_gsi_pkey_change(struct mlx5_ib_gsi_qp
*gsi
)