1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * tavor_qpmod.c
29 * Tavor Queue Pair Modify Routines
30 *
31 * This contains all the routines necessary to implement the Tavor
32 * ModifyQP() verb. This includes all the code for legal transitions to
33 * and from Reset, Init, RTR, RTS, SQD, SQErr, and Error.
34 */
35
36 #include <sys/sysmacros.h>
37 #include <sys/types.h>
38 #include <sys/conf.h>
39 #include <sys/ddi.h>
40 #include <sys/sunddi.h>
41 #include <sys/modctl.h>
42 #include <sys/bitmap.h>
43
44 #include <sys/ib/adapters/tavor/tavor.h>
45 #include <sys/ib/ib_pkt_hdrs.h>
46
47 static int tavor_qp_reset2init(tavor_state_t *state, tavor_qphdl_t qp,
48 ibt_qp_info_t *info_p);
49 static int tavor_qp_init2init(tavor_state_t *state, tavor_qphdl_t qp,
50 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
51 static int tavor_qp_init2rtr(tavor_state_t *state, tavor_qphdl_t qp,
52 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
53 static int tavor_qp_rtr2rts(tavor_state_t *state, tavor_qphdl_t qp,
54 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
55 static int tavor_qp_rts2rts(tavor_state_t *state, tavor_qphdl_t qp,
56 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
57 static int tavor_qp_rts2sqd(tavor_state_t *state, tavor_qphdl_t qp,
58 ibt_cep_modify_flags_t flags);
59 static int tavor_qp_sqd2rts(tavor_state_t *state, tavor_qphdl_t qp,
60 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
61 static int tavor_qp_sqd2sqd(tavor_state_t *state, tavor_qphdl_t qp,
62 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
63 static int tavor_qp_sqerr2rts(tavor_state_t *state, tavor_qphdl_t qp,
64 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
65 static int tavor_qp_to_error(tavor_state_t *state, tavor_qphdl_t qp);
66 static int tavor_qp_reset2err(tavor_state_t *state, tavor_qphdl_t qp);
67
68 static uint_t tavor_check_rdma_enable_flags(ibt_cep_modify_flags_t flags,
69 ibt_qp_info_t *info_p, tavor_hw_qpc_t *qpc);
70 static int tavor_qp_validate_resp_rsrc(tavor_state_t *state,
71 ibt_qp_rc_attr_t *rc, uint_t *rra_max);
72 static int tavor_qp_validate_init_depth(tavor_state_t *state,
73 ibt_qp_rc_attr_t *rc, uint_t *sra_max);
74 static int tavor_qp_validate_mtu(tavor_state_t *state, uint_t mtu);
75
76 /*
77 * tavor_qp_modify()
78 * Context: Can be called from interrupt or base context.
79 */
80 /* ARGSUSED */
81 int
tavor_qp_modify(tavor_state_t * state,tavor_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p,ibt_queue_sizes_t * actual_sz)82 tavor_qp_modify(tavor_state_t *state, tavor_qphdl_t qp,
83 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p,
84 ibt_queue_sizes_t *actual_sz)
85 {
86 ibt_cep_state_t cur_state, mod_state;
87 ibt_cep_modify_flags_t okflags;
88 int status;
89 char *errormsg;
90
91 TAVOR_TNF_ENTER(tavor_qp_modify);
92
93 /*
94 * Lock the QP so that we can modify it atomically. After grabbing
95 * the lock, get the current QP state. We will use this current QP
96 * state to determine the legal transitions (and the checks that need
97 * to be performed.)
98 * Below you will find a case for every possible QP state. In each
99 * case we check that no flags are set which are not valid for the
100 * possible transitions from that state. If these tests pass (and if
101 * the state transition we are attempting is legal), then we call
102 * one of the helper functions. Each of these functions does some
103 * additional setup before posting a Tavor firmware command for the
104 * appropriate state transition.
105 */
106 mutex_enter(&qp->qp_lock);
107
108 /*
109 * Verify that the transport type matches between the serv_type and the
110 * qp_trans. A caller to IBT must specify the qp_trans field as
111 * IBT_UD_SRV, IBT_RC_SRV, or IBT_UC_SRV, depending on the QP. We
112 * check here that the correct value was specified, based on our
113 * understanding of the QP serv type.
114 *
115 * Because callers specify part of a 'union' based on what QP type they
116 * think they're working with, this ensures that we do not pickup bogus
117 * data if the caller thought they were working with a different QP
118 * type.
119 */
120 if (!(TAVOR_QP_TYPE_VALID(info_p->qp_trans, qp->qp_serv_type))) {
121 mutex_exit(&qp->qp_lock);
122 TNF_PROBE_1(tavor_qp_modify_inv_qp_trans_fail,
123 TAVOR_TNF_ERROR, "", tnf_uint, qptrans,
124 info_p->qp_trans);
125 TAVOR_TNF_EXIT(tavor_qp_modify);
126 return (IBT_QP_SRV_TYPE_INVALID);
127 }
128
129 /*
130 * If this is a transition to RTS (which is valid from RTR, RTS,
131 * SQError, and SQ Drain) then we should honor the "current QP state"
132 * specified by the consumer. This means converting the IBTF QP state
133 * in "info_p->qp_current_state" to a Tavor QP state. Otherwise, we
134 * assume that we already know the current state (i.e. whatever it was
135 * last modified to or queried as - in "qp->qp_state").
136 */
137 mod_state = info_p->qp_state;
138
139 if (flags & IBT_CEP_SET_RTR_RTS) {
140 cur_state = TAVOR_QP_RTR; /* Ready to Receive */
141
142 } else if ((flags & IBT_CEP_SET_STATE) &&
143 (mod_state == IBT_STATE_RTS)) {
144
145 /* Convert the current IBTF QP state to a Tavor QP state */
146 switch (info_p->qp_current_state) {
147 case IBT_STATE_RTR:
148 cur_state = TAVOR_QP_RTR; /* Ready to Receive */
149 break;
150 case IBT_STATE_RTS:
151 cur_state = TAVOR_QP_RTS; /* Ready to Send */
152 break;
153 case IBT_STATE_SQE:
154 cur_state = TAVOR_QP_SQERR; /* Send Queue Error */
155 break;
156 case IBT_STATE_SQD:
157 cur_state = TAVOR_QP_SQD; /* SQ Drained */
158 break;
159 default:
160 mutex_exit(&qp->qp_lock);
161 TNF_PROBE_1(tavor_qp_modify_inv_currqpstate_fail,
162 TAVOR_TNF_ERROR, "", tnf_uint, qpstate,
163 info_p->qp_current_state);
164 TAVOR_TNF_EXIT(tavor_qp_modify);
165 return (IBT_QP_STATE_INVALID);
166 }
167 } else {
168 cur_state = qp->qp_state;
169 }
170
171 switch (cur_state) {
172 case TAVOR_QP_RESET:
173 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_RESET_INIT |
174 IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W |
175 IBT_CEP_SET_ATOMIC | IBT_CEP_SET_PKEY_IX |
176 IBT_CEP_SET_PORT | IBT_CEP_SET_QKEY);
177
178 /*
179 * Check for attempts to modify invalid attributes from the
180 * "Reset" state
181 */
182 if (flags & ~okflags) {
183 mutex_exit(&qp->qp_lock);
184 /* Set "status" and "errormsg" and goto failure */
185 TAVOR_TNF_FAIL(IBT_QP_ATTR_RO, "reset: invalid flag");
186 goto qpmod_fail;
187 }
188
189 /*
190 * Verify state transition is to either "Init", back to
191 * "Reset", or to "Error".
192 */
193 if ((flags & IBT_CEP_SET_RESET_INIT) &&
194 (flags & IBT_CEP_SET_STATE) &&
195 (mod_state != IBT_STATE_INIT)) {
196 /* Invalid transition - ambiguous flags */
197 mutex_exit(&qp->qp_lock);
198 /* Set "status" and "errormsg" and goto failure */
199 TAVOR_TNF_FAIL(IBT_QP_STATE_INVALID,
200 "reset: ambiguous flags");
201 goto qpmod_fail;
202
203 } else if ((flags & IBT_CEP_SET_RESET_INIT) ||
204 ((flags & IBT_CEP_SET_STATE) &&
205 (mod_state == IBT_STATE_INIT))) {
206 /*
207 * Attempt to transition from "Reset" to "Init"
208 */
209 status = tavor_qp_reset2init(state, qp, info_p);
210 if (status != DDI_SUCCESS) {
211 mutex_exit(&qp->qp_lock);
212 /* Set "status"/"errormsg", goto failure */
213 TAVOR_TNF_FAIL(status, "reset to init");
214 goto qpmod_fail;
215 }
216 qp->qp_state = TAVOR_QP_INIT;
217
218 } else if ((flags & IBT_CEP_SET_STATE) &&
219 (mod_state == IBT_STATE_RESET)) {
220 /*
221 * Attempt to transition from "Reset" back to "Reset"
222 * Nothing to do here really... just drop the lock
223 * and return success. The qp->qp_state should
224 * already be set to TAVOR_QP_RESET.
225 *
226 * Note: We return here because we do not want to fall
227 * through to the tavor_wrid_from_reset_handling()
228 * routine below (since we are not really moving
229 * _out_ of the "Reset" state.
230 */
231 mutex_exit(&qp->qp_lock);
232 TNF_PROBE_0_DEBUG(tavor_qp_modify_rst2rst,
233 TAVOR_TNF_TRACE, "");
234 TAVOR_TNF_EXIT(tavor_qp_modify);
235 return (DDI_SUCCESS);
236
237 } else if ((flags & IBT_CEP_SET_STATE) &&
238 (mod_state == IBT_STATE_ERROR)) {
239 /*
240 * Attempt to transition from "Reset" to "Error"
241 */
242 status = tavor_qp_reset2err(state, qp);
243 if (status != DDI_SUCCESS) {
244 mutex_exit(&qp->qp_lock);
245 /* Set "status"/"errormsg", goto failure */
246 TAVOR_TNF_FAIL(status, "reset to error");
247 goto qpmod_fail;
248 }
249 qp->qp_state = TAVOR_QP_ERR;
250
251 } else {
252 /* Invalid transition - return error */
253 mutex_exit(&qp->qp_lock);
254 /* Set "status" and "errormsg" and goto failure */
255 TAVOR_TNF_FAIL(IBT_QP_STATE_INVALID,
256 "reset: invalid transition");
257 goto qpmod_fail;
258 }
259
260 /*
261 * Do any additional handling necessary here for the transition
262 * from the "Reset" state (e.g. re-initialize the workQ WRID
263 * lists). Note: If tavor_wrid_from_reset_handling() fails,
264 * then we attempt to transition the QP back to the "Reset"
265 * state. If that fails, then it is an indication of a serious
266 * problem (either HW or SW). So we print out a warning
267 * message and return failure.
268 */
269 status = tavor_wrid_from_reset_handling(state, qp);
270 if (status != DDI_SUCCESS) {
271 if (tavor_qp_to_reset(state, qp) != DDI_SUCCESS) {
272 TAVOR_WARNING(state, "failed to reset QP");
273 }
274 qp->qp_state = TAVOR_QP_RESET;
275
276 mutex_exit(&qp->qp_lock);
277 /* Set "status" and "errormsg" and goto failure */
278 TAVOR_TNF_FAIL(status, "reset: wrid_from_reset hdl");
279 goto qpmod_fail;
280 }
281 break;
282
283 case TAVOR_QP_INIT:
284 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_INIT_RTR |
285 IBT_CEP_SET_ADDS_VECT | IBT_CEP_SET_RDMARA_IN |
286 IBT_CEP_SET_MIN_RNR_NAK | IBT_CEP_SET_ALT_PATH |
287 IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W |
288 IBT_CEP_SET_ATOMIC | IBT_CEP_SET_PKEY_IX |
289 IBT_CEP_SET_QKEY | IBT_CEP_SET_PORT);
290
291 /*
292 * Check for attempts to modify invalid attributes from the
293 * "Init" state
294 */
295 if (flags & ~okflags) {
296 mutex_exit(&qp->qp_lock);
297 /* Set "status" and "errormsg" and goto failure */
298 TAVOR_TNF_FAIL(IBT_QP_ATTR_RO, "init: invalid flag");
299 goto qpmod_fail;
300 }
301
302 /*
303 * Verify state transition is to either "RTR", back to "Init",
304 * to "Reset", or to "Error"
305 */
306 if ((flags & IBT_CEP_SET_INIT_RTR) &&
307 (flags & IBT_CEP_SET_STATE) &&
308 (mod_state != IBT_STATE_RTR)) {
309 /* Invalid transition - ambiguous flags */
310 mutex_exit(&qp->qp_lock);
311 /* Set "status" and "errormsg" and goto failure */
312 TAVOR_TNF_FAIL(IBT_QP_STATE_INVALID,
313 "init: ambiguous flags");
314 goto qpmod_fail;
315
316 } else if ((flags & IBT_CEP_SET_INIT_RTR) ||
317 ((flags & IBT_CEP_SET_STATE) &&
318 (mod_state == IBT_STATE_RTR))) {
319 /*
320 * Attempt to transition from "Init" to "RTR"
321 */
322 status = tavor_qp_init2rtr(state, qp, flags, info_p);
323 if (status != DDI_SUCCESS) {
324 mutex_exit(&qp->qp_lock);
325 /* Set "status"/"errormsg", goto failure */
326 TAVOR_TNF_FAIL(status, "init to rtr");
327 goto qpmod_fail;
328 }
329 qp->qp_state = TAVOR_QP_RTR;
330
331 } else if ((flags & IBT_CEP_SET_STATE) &&
332 (mod_state == IBT_STATE_INIT)) {
333 /*
334 * Attempt to transition from "Init" to "Init"
335 */
336 status = tavor_qp_init2init(state, qp, flags, info_p);
337 if (status != DDI_SUCCESS) {
338 mutex_exit(&qp->qp_lock);
339 /* Set "status"/"errormsg", goto failure */
340 TAVOR_TNF_FAIL(status, "init to init");
341 goto qpmod_fail;
342 }
343 qp->qp_state = TAVOR_QP_INIT;
344
345 } else if ((flags & IBT_CEP_SET_STATE) &&
346 (mod_state == IBT_STATE_RESET)) {
347 /*
348 * Attempt to transition from "Init" to "Reset"
349 */
350 status = tavor_qp_to_reset(state, qp);
351 if (status != DDI_SUCCESS) {
352 mutex_exit(&qp->qp_lock);
353 /* Set "status"/"errormsg", goto failure */
354 TAVOR_TNF_FAIL(status, "init to reset");
355 goto qpmod_fail;
356 }
357 qp->qp_state = TAVOR_QP_RESET;
358
359 /*
360 * Do any additional handling necessary for the
361 * transition _to_ the "Reset" state (e.g. update the
362 * workQ WRID lists)
363 */
364 tavor_wrid_to_reset_handling(state, qp);
365
366 } else if ((flags & IBT_CEP_SET_STATE) &&
367 (mod_state == IBT_STATE_ERROR)) {
368 /*
369 * Attempt to transition from "Init" to "Error"
370 */
371 status = tavor_qp_to_error(state, qp);
372 if (status != DDI_SUCCESS) {
373 mutex_exit(&qp->qp_lock);
374 /* Set "status"/"errormsg", goto failure */
375 TAVOR_TNF_FAIL(status, "init to error");
376 goto qpmod_fail;
377 }
378 qp->qp_state = TAVOR_QP_ERR;
379
380 } else {
381 /* Invalid transition - return error */
382 mutex_exit(&qp->qp_lock);
383 /* Set "status" and "errormsg" and goto failure */
384 TAVOR_TNF_FAIL(IBT_QP_STATE_INVALID,
385 "init: invalid transition");
386 goto qpmod_fail;
387 }
388 break;
389
390 case TAVOR_QP_RTR:
391 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_RTR_RTS |
392 IBT_CEP_SET_TIMEOUT | IBT_CEP_SET_RETRY |
393 IBT_CEP_SET_RNR_NAK_RETRY | IBT_CEP_SET_RDMARA_OUT |
394 IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W |
395 IBT_CEP_SET_ATOMIC | IBT_CEP_SET_QKEY |
396 IBT_CEP_SET_ALT_PATH | IBT_CEP_SET_MIG |
397 IBT_CEP_SET_MIN_RNR_NAK);
398
399 /*
400 * Check for attempts to modify invalid attributes from the
401 * "RTR" state
402 */
403 if (flags & ~okflags) {
404 mutex_exit(&qp->qp_lock);
405 /* Set "status" and "errormsg" and goto failure */
406 TAVOR_TNF_FAIL(IBT_QP_ATTR_RO, "rtr: invalid flag");
407 goto qpmod_fail;
408 }
409
410 /*
411 * Verify state transition is to either "RTS", "Reset",
412 * or "Error"
413 */
414 if ((flags & IBT_CEP_SET_RTR_RTS) &&
415 (flags & IBT_CEP_SET_STATE) &&
416 (mod_state != IBT_STATE_RTS)) {
417 /* Invalid transition - ambiguous flags */
418 mutex_exit(&qp->qp_lock);
419 /* Set "status" and "errormsg" and goto failure */
420 TAVOR_TNF_FAIL(IBT_QP_STATE_INVALID,
421 "reset: ambiguous flags");
422 goto qpmod_fail;
423
424 } else if ((flags & IBT_CEP_SET_RTR_RTS) ||
425 ((flags & IBT_CEP_SET_STATE) &&
426 (mod_state == IBT_STATE_RTS))) {
427 /*
428 * Attempt to transition from "RTR" to "RTS"
429 */
430 status = tavor_qp_rtr2rts(state, qp, flags, info_p);
431 if (status != DDI_SUCCESS) {
432 mutex_exit(&qp->qp_lock);
433 /* Set "status"/"errormsg", goto failure */
434 TAVOR_TNF_FAIL(status, "rtr to rts");
435 goto qpmod_fail;
436 }
437 qp->qp_state = TAVOR_QP_RTS;
438
439 } else if ((flags & IBT_CEP_SET_STATE) &&
440 (mod_state == IBT_STATE_RESET)) {
441 /*
442 * Attempt to transition from "RTR" to "Reset"
443 */
444 status = tavor_qp_to_reset(state, qp);
445 if (status != DDI_SUCCESS) {
446 mutex_exit(&qp->qp_lock);
447 /* Set "status"/"errormsg", goto failure */
448 TAVOR_TNF_FAIL(status, "rtr to reset");
449 goto qpmod_fail;
450 }
451 qp->qp_state = TAVOR_QP_RESET;
452
453 /*
454 * Do any additional handling necessary for the
455 * transition _to_ the "Reset" state (e.g. update the
456 * workQ WRID lists)
457 */
458 tavor_wrid_to_reset_handling(state, qp);
459
460 } else if ((flags & IBT_CEP_SET_STATE) &&
461 (mod_state == IBT_STATE_ERROR)) {
462 /*
463 * Attempt to transition from "RTR" to "Error"
464 */
465 status = tavor_qp_to_error(state, qp);
466 if (status != DDI_SUCCESS) {
467 mutex_exit(&qp->qp_lock);
468 /* Set "status"/"errormsg", goto failure */
469 TAVOR_TNF_FAIL(status, "rtr to error");
470 goto qpmod_fail;
471 }
472 qp->qp_state = TAVOR_QP_ERR;
473
474 } else {
475 /* Invalid transition - return error */
476 mutex_exit(&qp->qp_lock);
477 /* Set "status" and "errormsg" and goto failure */
478 TAVOR_TNF_FAIL(IBT_QP_STATE_INVALID,
479 "rtr: invalid transition");
480 goto qpmod_fail;
481 }
482 break;
483
484 case TAVOR_QP_RTS:
485 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_RDMA_R |
486 IBT_CEP_SET_RDMA_W | IBT_CEP_SET_ATOMIC |
487 IBT_CEP_SET_QKEY | IBT_CEP_SET_ALT_PATH |
488 IBT_CEP_SET_MIG | IBT_CEP_SET_MIN_RNR_NAK |
489 IBT_CEP_SET_SQD_EVENT);
490
491 /*
492 * Check for attempts to modify invalid attributes from the
493 * "RTS" state
494 */
495 if (flags & ~okflags) {
496 mutex_exit(&qp->qp_lock);
497 /* Set "status" and "errormsg" and goto failure */
498 TAVOR_TNF_FAIL(IBT_QP_ATTR_RO, "rts: invalid flag");
499 goto qpmod_fail;
500 }
501
502 /*
503 * Verify state transition is to either "RTS", "SQD", "Reset",
504 * or "Error"
505 */
506 if ((flags & IBT_CEP_SET_STATE) &&
507 (mod_state == IBT_STATE_RTS)) {
508 /*
509 * Attempt to transition from "RTS" to "RTS"
510 */
511 status = tavor_qp_rts2rts(state, qp, flags, info_p);
512 if (status != DDI_SUCCESS) {
513 mutex_exit(&qp->qp_lock);
514 /* Set "status"/"errormsg", goto failure */
515 TAVOR_TNF_FAIL(status, "rts to rts");
516 goto qpmod_fail;
517 }
518 /* qp->qp_state = TAVOR_QP_RTS; */
519
520 } else if ((flags & IBT_CEP_SET_STATE) &&
521 (mod_state == IBT_STATE_SQD)) {
522 /*
523 * Attempt to transition from "RTS" to "SQD"
524 */
525 status = tavor_qp_rts2sqd(state, qp, flags);
526 if (status != DDI_SUCCESS) {
527 mutex_exit(&qp->qp_lock);
528 /* Set "status"/"errormsg", goto failure */
529 TAVOR_TNF_FAIL(status, "rts to sqd");
530 goto qpmod_fail;
531 }
532 qp->qp_state = TAVOR_QP_SQD;
533
534 } else if ((flags & IBT_CEP_SET_STATE) &&
535 (mod_state == IBT_STATE_RESET)) {
536 /*
537 * Attempt to transition from "RTS" to "Reset"
538 */
539 status = tavor_qp_to_reset(state, qp);
540 if (status != DDI_SUCCESS) {
541 mutex_exit(&qp->qp_lock);
542 /* Set "status"/"errormsg", goto failure */
543 TAVOR_TNF_FAIL(status, "rts to reset");
544 goto qpmod_fail;
545 }
546 qp->qp_state = TAVOR_QP_RESET;
547
548 /*
549 * Do any additional handling necessary for the
550 * transition _to_ the "Reset" state (e.g. update the
551 * workQ WRID lists)
552 */
553 tavor_wrid_to_reset_handling(state, qp);
554
555 } else if ((flags & IBT_CEP_SET_STATE) &&
556 (mod_state == IBT_STATE_ERROR)) {
557 /*
558 * Attempt to transition from "RTS" to "Error"
559 */
560 status = tavor_qp_to_error(state, qp);
561 if (status != DDI_SUCCESS) {
562 mutex_exit(&qp->qp_lock);
563 /* Set "status"/"errormsg", goto failure */
564 TAVOR_TNF_FAIL(status, "rts to error");
565 goto qpmod_fail;
566 }
567 qp->qp_state = TAVOR_QP_ERR;
568
569 } else {
570 /* Invalid transition - return error */
571 mutex_exit(&qp->qp_lock);
572 /* Set "status" and "errormsg" and goto failure */
573 TAVOR_TNF_FAIL(IBT_QP_STATE_INVALID,
574 "rts: invalid transition");
575 goto qpmod_fail;
576 }
577 break;
578
579 case TAVOR_QP_SQERR:
580 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_RDMA_R |
581 IBT_CEP_SET_RDMA_W | IBT_CEP_SET_ATOMIC |
582 IBT_CEP_SET_QKEY | IBT_CEP_SET_MIN_RNR_NAK);
583
584 /*
585 * Check for attempts to modify invalid attributes from the
586 * "SQErr" state
587 */
588 if (flags & ~okflags) {
589 mutex_exit(&qp->qp_lock);
590 /* Set "status" and "errormsg" and goto failure */
591 TAVOR_TNF_FAIL(IBT_QP_ATTR_RO, "sqerr: invalid flag");
592 goto qpmod_fail;
593 }
594
595 /*
596 * Verify state transition is to either "RTS", "Reset", or
597 * "Error"
598 */
599 if ((flags & IBT_CEP_SET_STATE) &&
600 (mod_state == IBT_STATE_RTS)) {
601 /*
602 * Attempt to transition from "SQErr" to "RTS"
603 */
604 status = tavor_qp_sqerr2rts(state, qp, flags, info_p);
605 if (status != DDI_SUCCESS) {
606 mutex_exit(&qp->qp_lock);
607 /* Set "status"/"errormsg", goto failure */
608 TAVOR_TNF_FAIL(status, "sqerr to rts");
609 goto qpmod_fail;
610 }
611 qp->qp_state = TAVOR_QP_RTS;
612
613 } else if ((flags & IBT_CEP_SET_STATE) &&
614 (mod_state == IBT_STATE_RESET)) {
615 /*
616 * Attempt to transition from "SQErr" to "Reset"
617 */
618 status = tavor_qp_to_reset(state, qp);
619 if (status != DDI_SUCCESS) {
620 mutex_exit(&qp->qp_lock);
621 /* Set "status"/"errormsg", goto failure */
622 TAVOR_TNF_FAIL(status, "sqerr to reset");
623 goto qpmod_fail;
624 }
625 qp->qp_state = TAVOR_QP_RESET;
626
627 /*
628 * Do any additional handling necessary for the
629 * transition _to_ the "Reset" state (e.g. update the
630 * workQ WRID lists)
631 */
632 tavor_wrid_to_reset_handling(state, qp);
633
634 } else if ((flags & IBT_CEP_SET_STATE) &&
635 (mod_state == IBT_STATE_ERROR)) {
636 /*
637 * Attempt to transition from "SQErr" to "Error"
638 */
639 status = tavor_qp_to_error(state, qp);
640 if (status != DDI_SUCCESS) {
641 mutex_exit(&qp->qp_lock);
642 /* Set "status"/"errormsg", goto failure */
643 TAVOR_TNF_FAIL(status, "sqerr to error");
644 goto qpmod_fail;
645 }
646 qp->qp_state = TAVOR_QP_ERR;
647
648 } else {
649 /* Invalid transition - return error */
650 mutex_exit(&qp->qp_lock);
651 /* Set "status" and "errormsg" and goto failure */
652 TAVOR_TNF_FAIL(IBT_QP_STATE_INVALID,
653 "sqerr: invalid transition");
654 goto qpmod_fail;
655 }
656 break;
657
658 case TAVOR_QP_SQD:
659 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_ADDS_VECT |
660 IBT_CEP_SET_ALT_PATH | IBT_CEP_SET_MIG |
661 IBT_CEP_SET_RDMARA_OUT | IBT_CEP_SET_RDMARA_IN |
662 IBT_CEP_SET_QKEY | IBT_CEP_SET_PKEY_IX |
663 IBT_CEP_SET_TIMEOUT | IBT_CEP_SET_RETRY |
664 IBT_CEP_SET_RNR_NAK_RETRY | IBT_CEP_SET_PORT |
665 IBT_CEP_SET_MIN_RNR_NAK | IBT_CEP_SET_RDMA_R |
666 IBT_CEP_SET_RDMA_W | IBT_CEP_SET_ATOMIC);
667
668 /*
669 * Check for attempts to modify invalid attributes from the
670 * "SQD" state
671 */
672 if (flags & ~okflags) {
673 mutex_exit(&qp->qp_lock);
674 /* Set "status" and "errormsg" and goto failure */
675 TAVOR_TNF_FAIL(IBT_QP_ATTR_RO, "sqd: invalid flag");
676 goto qpmod_fail;
677 }
678
679 /*
680 * Verify state transition is to either "SQD", "RTS", "Reset",
681 * or "Error"
682 */
683
684 if ((flags & IBT_CEP_SET_STATE) &&
685 (mod_state == IBT_STATE_SQD)) {
686 /*
687 * Attempt to transition from "SQD" to "SQD"
688 */
689 status = tavor_qp_sqd2sqd(state, qp, flags, info_p);
690 if (status != DDI_SUCCESS) {
691 mutex_exit(&qp->qp_lock);
692 /* Set "status"/"errormsg", goto failure */
693 TAVOR_TNF_FAIL(status, "sqd to sqd");
694 goto qpmod_fail;
695 }
696 qp->qp_state = TAVOR_QP_SQD;
697
698 } else if ((flags & IBT_CEP_SET_STATE) &&
699 (mod_state == IBT_STATE_RTS)) {
700 /*
701 * If still draining SQ, then fail transition attempt
702 * to RTS.
703 */
704 if (qp->qp_sqd_still_draining) {
705 mutex_exit(&qp->qp_lock);
706 /* Set "status"/"errormsg", goto failure */
707 status = IBT_QP_STATE_INVALID;
708 TAVOR_TNF_FAIL(status, "sqd to rts; draining");
709 goto qpmod_fail;
710 }
711
712 /*
713 * Attempt to transition from "SQD" to "RTS"
714 */
715 status = tavor_qp_sqd2rts(state, qp, flags, info_p);
716 if (status != DDI_SUCCESS) {
717 mutex_exit(&qp->qp_lock);
718 /* Set "status"/"errormsg", goto failure */
719 TAVOR_TNF_FAIL(status, "sqd to rts");
720 goto qpmod_fail;
721 }
722 qp->qp_state = TAVOR_QP_RTS;
723
724 } else if ((flags & IBT_CEP_SET_STATE) &&
725 (mod_state == IBT_STATE_RESET)) {
726 /*
727 * Attempt to transition from "SQD" to "Reset"
728 */
729 status = tavor_qp_to_reset(state, qp);
730 if (status != DDI_SUCCESS) {
731 mutex_exit(&qp->qp_lock);
732 /* Set "status"/"errormsg", goto failure */
733 TAVOR_TNF_FAIL(status, "sqd to reset");
734 goto qpmod_fail;
735 }
736 qp->qp_state = TAVOR_QP_RESET;
737
738 /*
739 * Do any additional handling necessary for the
740 * transition _to_ the "Reset" state (e.g. update the
741 * workQ WRID lists)
742 */
743 tavor_wrid_to_reset_handling(state, qp);
744
745 } else if ((flags & IBT_CEP_SET_STATE) &&
746 (mod_state == IBT_STATE_ERROR)) {
747 /*
748 * Attempt to transition from "SQD" to "Error"
749 */
750 status = tavor_qp_to_error(state, qp);
751 if (status != DDI_SUCCESS) {
752 mutex_exit(&qp->qp_lock);
753 /* Set "status"/"errormsg", goto failure */
754 TAVOR_TNF_FAIL(status, "sqd to error");
755 goto qpmod_fail;
756 }
757 qp->qp_state = TAVOR_QP_ERR;
758
759 } else {
760 /* Invalid transition - return error */
761 mutex_exit(&qp->qp_lock);
762 /* Set "status" and "errormsg" and goto failure */
763 TAVOR_TNF_FAIL(IBT_QP_STATE_INVALID,
764 "sqd: invalid transition");
765 goto qpmod_fail;
766 }
767 break;
768
769 case TAVOR_QP_ERR:
770 /*
771 * Verify state transition is to either "Reset" or back to
772 * "Error"
773 */
774 if ((flags & IBT_CEP_SET_STATE) &&
775 (mod_state == IBT_STATE_RESET)) {
776 /*
777 * Attempt to transition from "Error" to "Reset"
778 */
779 status = tavor_qp_to_reset(state, qp);
780 if (status != DDI_SUCCESS) {
781 mutex_exit(&qp->qp_lock);
782 /* Set "status"/"errormsg", goto failure */
783 TAVOR_TNF_FAIL(status, "error to reset");
784 goto qpmod_fail;
785 }
786 qp->qp_state = TAVOR_QP_RESET;
787
788 /*
789 * Do any additional handling necessary for the
790 * transition _to_ the "Reset" state (e.g. update the
791 * workQ WRID lists)
792 */
793 tavor_wrid_to_reset_handling(state, qp);
794
795 } else if ((flags & IBT_CEP_SET_STATE) &&
796 (mod_state == IBT_STATE_ERROR)) {
797 /*
798 * Attempt to transition from "Error" back to "Error"
799 * Nothing to do here really... just drop the lock
800 * and return success. The qp->qp_state should
801 * already be set to TAVOR_QP_ERR.
802 *
803 */
804 mutex_exit(&qp->qp_lock);
805 TNF_PROBE_0_DEBUG(tavor_qp_modify_err2err,
806 TAVOR_TNF_TRACE, "");
807 TAVOR_TNF_EXIT(tavor_qp_modify);
808 return (DDI_SUCCESS);
809
810 } else {
811 /* Invalid transition - return error */
812 mutex_exit(&qp->qp_lock);
813 /* Set "status" and "errormsg" and goto failure */
814 TAVOR_TNF_FAIL(IBT_QP_STATE_INVALID,
815 "error: invalid transition");
816 goto qpmod_fail;
817 }
818 break;
819
820 default:
821 /*
822 * Invalid QP state. If we got here then it's a warning of
823 * a probably serious problem. So print a message and return
824 * failure
825 */
826 mutex_exit(&qp->qp_lock);
827 TAVOR_WARNING(state, "unknown QP state in modify");
828 /* Set "status" and "errormsg" and goto failure */
829 TAVOR_TNF_FAIL(IBT_QP_STATE_INVALID, "invalid curr QP state");
830 goto qpmod_fail;
831 }
832
833 mutex_exit(&qp->qp_lock);
834 TAVOR_TNF_EXIT(tavor_qp_modify);
835 return (DDI_SUCCESS);
836
837 qpmod_fail:
838 TNF_PROBE_1(tavor_qp_modify_fail, TAVOR_TNF_ERROR, "",
839 tnf_string, msg, errormsg);
840 TAVOR_TNF_EXIT(tavor_qp_modify);
841 return (status);
842 }
843
844
845 /*
846 * tavor_qp_reset2init()
847 * Context: Can be called from interrupt or base context.
848 */
849 static int
tavor_qp_reset2init(tavor_state_t * state,tavor_qphdl_t qp,ibt_qp_info_t * info_p)850 tavor_qp_reset2init(tavor_state_t *state, tavor_qphdl_t qp,
851 ibt_qp_info_t *info_p)
852 {
853 tavor_hw_qpc_t *qpc;
854 ibt_qp_rc_attr_t *rc;
855 ibt_qp_ud_attr_t *ud;
856 ibt_qp_uc_attr_t *uc;
857 uint_t portnum, pkeyindx;
858 int status;
859
860 TAVOR_TNF_ENTER(tavor_qp_reset2init);
861
862 ASSERT(MUTEX_HELD(&qp->qp_lock));
863
864 /*
865 * Grab the temporary QPC entry from QP software state
866 */
867 qpc = &qp->qpc;
868
869 /*
870 * Fill in the common and/or Tavor-specific fields in the QPC
871 */
872 if (qp->qp_is_special) {
873 qpc->serv_type = TAVOR_QP_MLX;
874 } else {
875 qpc->serv_type = qp->qp_serv_type;
876 }
877 qpc->pm_state = TAVOR_QP_PMSTATE_MIGRATED;
878 qpc->de = TAVOR_QP_DESC_EVT_ENABLED;
879 qpc->sched_q = TAVOR_QP_SCHEDQ_GET(qp->qp_qpnum);
880 if (qp->qp_is_umap) {
881 qpc->usr_page = qp->qp_uarpg;
882 } else {
883 qpc->usr_page = 0;
884 }
885 qpc->pd = qp->qp_pdhdl->pd_pdnum;
886 qpc->wqe_baseaddr = 0;
887 qpc->wqe_lkey = qp->qp_mrhdl->mr_lkey;
888 qpc->ssc = qp->qp_sq_sigtype;
889 qpc->cqn_snd = qp->qp_sq_cqhdl->cq_cqnum;
890 qpc->rsc = TAVOR_QP_RQ_ALL_SIGNALED;
891 qpc->cqn_rcv = qp->qp_rq_cqhdl->cq_cqnum;
892 qpc->srq_en = qp->qp_srq_en;
893
894 if (qp->qp_srq_en == TAVOR_QP_SRQ_ENABLED) {
895 qpc->srq_number = qp->qp_srqhdl->srq_srqnum;
896 } else {
897 qpc->srq_number = 0;
898 }
899
900 /*
901 * Now fill in the QPC fields which are specific to transport type
902 */
903 if (qp->qp_serv_type == TAVOR_QP_UD) {
904 ud = &info_p->qp_transport.ud;
905
906 /* Set the QKey */
907 qpc->qkey = ud->ud_qkey;
908
909 /* Check for valid port number and fill it in */
910 portnum = ud->ud_port;
911 if (tavor_portnum_is_valid(state, portnum)) {
912 qpc->pri_addr_path.portnum = portnum;
913 } else {
914 TNF_PROBE_1(tavor_qp_reset2init_inv_port_fail,
915 TAVOR_TNF_ERROR, "", tnf_uint, port, portnum);
916 TAVOR_TNF_EXIT(tavor_qp_reset2init);
917 return (IBT_HCA_PORT_INVALID);
918 }
919
920 /* Check for valid PKey index and fill it in */
921 pkeyindx = ud->ud_pkey_ix;
922 if (tavor_pkeyindex_is_valid(state, pkeyindx)) {
923 qpc->pri_addr_path.pkey_indx = pkeyindx;
924 qp->qp_pkeyindx = pkeyindx;
925 } else {
926 TNF_PROBE_1(tavor_qp_reset2init_inv_pkey_fail,
927 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx, pkeyindx);
928 TAVOR_TNF_EXIT(tavor_qp_reset2init);
929 return (IBT_PKEY_IX_ILLEGAL);
930 }
931
932 } else if (qp->qp_serv_type == TAVOR_QP_RC) {
933 rc = &info_p->qp_transport.rc;
934
935 /* Set the RDMA (recv) enable/disable flags */
936 qpc->rre = (info_p->qp_flags & IBT_CEP_RDMA_RD) ? 1 : 0;
937 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
938 qpc->rae = (info_p->qp_flags & IBT_CEP_ATOMIC) ? 1 : 0;
939
940 /* Check for valid port number and fill it in */
941 portnum = rc->rc_path.cep_hca_port_num;
942 if (tavor_portnum_is_valid(state, portnum)) {
943 qpc->pri_addr_path.portnum = portnum;
944 } else {
945 TNF_PROBE_1(tavor_qp_reset2init_inv_port_fail,
946 TAVOR_TNF_ERROR, "", tnf_uint, port, portnum);
947 TAVOR_TNF_EXIT(tavor_qp_reset2init);
948 return (IBT_HCA_PORT_INVALID);
949 }
950
951 /* Check for valid PKey index and fill it in */
952 pkeyindx = rc->rc_path.cep_pkey_ix;
953 if (tavor_pkeyindex_is_valid(state, pkeyindx)) {
954 qpc->pri_addr_path.pkey_indx = pkeyindx;
955 } else {
956 TNF_PROBE_1(tavor_qp_reset2init_inv_pkey_fail,
957 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx, pkeyindx);
958 TAVOR_TNF_EXIT(tavor_qp_reset2init);
959 return (IBT_PKEY_IX_ILLEGAL);
960 }
961
962 } else if (qp->qp_serv_type == TAVOR_QP_UC) {
963 uc = &info_p->qp_transport.uc;
964
965 /*
966 * Set the RDMA (recv) enable/disable flags. Note: RDMA Read
967 * and Atomic are ignored by default.
968 */
969 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
970
971 /* Check for valid port number and fill it in */
972 portnum = uc->uc_path.cep_hca_port_num;
973 if (tavor_portnum_is_valid(state, portnum)) {
974 qpc->pri_addr_path.portnum = portnum;
975 } else {
976 TNF_PROBE_1(tavor_qp_reset2init_inv_port_fail,
977 TAVOR_TNF_ERROR, "", tnf_uint, port, portnum);
978 TAVOR_TNF_EXIT(tavor_qp_reset2init);
979 return (IBT_HCA_PORT_INVALID);
980 }
981
982 /* Check for valid PKey index and fill it in */
983 pkeyindx = uc->uc_path.cep_pkey_ix;
984 if (tavor_pkeyindex_is_valid(state, pkeyindx)) {
985 qpc->pri_addr_path.pkey_indx = pkeyindx;
986 } else {
987 TNF_PROBE_1(tavor_qp_reset2init_inv_pkey_fail,
988 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx, pkeyindx);
989 TAVOR_TNF_EXIT(tavor_qp_reset2init);
990 return (IBT_PKEY_IX_ILLEGAL);
991 }
992 } else {
993 /*
994 * Invalid QP transport type. If we got here then it's a
995 * warning of a probably serious problem. So print a message
996 * and return failure
997 */
998 TAVOR_WARNING(state, "unknown QP transport type in rst2init");
999 TNF_PROBE_0(tavor_qp_reset2init_inv_transtype_fail,
1000 TAVOR_TNF_ERROR, "");
1001 TAVOR_TNF_EXIT(tavor_qp_reset2init);
1002 return (ibc_get_ci_failure(0));
1003 }
1004
1005 /*
1006 * Post the RST2INIT_QP command to the Tavor firmware
1007 *
1008 * We do a TAVOR_NOSLEEP here because we are still holding the
1009 * "qp_lock". If we got raised to interrupt level by priority
1010 * inversion, we do not want to block in this routine waiting for
1011 * success.
1012 */
1013 status = tavor_cmn_qp_cmd_post(state, RST2INIT_QP, qpc, qp->qp_qpnum,
1014 0, TAVOR_CMD_NOSLEEP_SPIN);
1015 if (status != TAVOR_CMD_SUCCESS) {
1016 cmn_err(CE_CONT, "Tavor: RST2INIT_QP command failed: %08x\n",
1017 status);
1018 TNF_PROBE_1(tavor_qp_reset2init_cmd_fail, TAVOR_TNF_ERROR, "",
1019 tnf_uint, status, status);
1020 TAVOR_TNF_EXIT(tavor_qp_reset2init);
1021 return (ibc_get_ci_failure(0));
1022 }
1023
1024 TAVOR_TNF_EXIT(tavor_qp_reset2init);
1025 return (DDI_SUCCESS);
1026 }
1027
1028
1029 /*
1030 * tavor_qp_init2init()
1031 * Context: Can be called from interrupt or base context.
1032 */
1033 static int
tavor_qp_init2init(tavor_state_t * state,tavor_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p)1034 tavor_qp_init2init(tavor_state_t *state, tavor_qphdl_t qp,
1035 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p)
1036 {
1037 tavor_hw_qpc_t *qpc;
1038 ibt_qp_rc_attr_t *rc;
1039 ibt_qp_ud_attr_t *ud;
1040 ibt_qp_uc_attr_t *uc;
1041 uint_t portnum, pkeyindx;
1042 uint32_t opmask = 0;
1043 int status;
1044
1045 TAVOR_TNF_ENTER(tavor_qp_init2init);
1046
1047 ASSERT(MUTEX_HELD(&qp->qp_lock));
1048
1049 /*
1050 * Grab the temporary QPC entry from QP software state
1051 */
1052 qpc = &qp->qpc;
1053
1054 /*
1055 * Since there are no common and/or Tavor-specific fields to be filled
1056 * in for this command, we begin with the QPC fields which are
1057 * specific to transport type.
1058 */
1059 if (qp->qp_serv_type == TAVOR_QP_UD) {
1060 ud = &info_p->qp_transport.ud;
1061
1062 /*
1063 * If we are attempting to modify the port for this QP, then
1064 * check for valid port number and fill it in. Also set the
1065 * appropriate flag in the "opmask" parameter.
1066 */
1067 if (flags & IBT_CEP_SET_PORT) {
1068 portnum = ud->ud_port;
1069 if (tavor_portnum_is_valid(state, portnum)) {
1070 qpc->pri_addr_path.portnum = portnum;
1071 } else {
1072 TNF_PROBE_1(tavor_qp_init2init_inv_port_fail,
1073 TAVOR_TNF_ERROR, "", tnf_uint, port,
1074 portnum);
1075 TAVOR_TNF_EXIT(tavor_qp_init2init);
1076 return (IBT_HCA_PORT_INVALID);
1077 }
1078 opmask |= TAVOR_CMD_OP_PRIM_PORT;
1079 }
1080
1081 /*
1082 * If we are attempting to modify the PKey index for this QP,
1083 * then check for valid PKey index and fill it in. Also set
1084 * the appropriate flag in the "opmask" parameter.
1085 */
1086 if (flags & IBT_CEP_SET_PKEY_IX) {
1087 pkeyindx = ud->ud_pkey_ix;
1088 if (tavor_pkeyindex_is_valid(state, pkeyindx)) {
1089 qpc->pri_addr_path.pkey_indx = pkeyindx;
1090 opmask |= TAVOR_CMD_OP_PKEYINDX;
1091 qp->qp_pkeyindx = pkeyindx;
1092 } else {
1093 TNF_PROBE_1(tavor_qp_init2init_inv_pkey_fail,
1094 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx,
1095 pkeyindx);
1096 TAVOR_TNF_EXIT(tavor_qp_init2init);
1097 return (IBT_PKEY_IX_ILLEGAL);
1098 }
1099 }
1100
1101 /*
1102 * If we are attempting to modify the QKey for this QP, then
1103 * fill it in and set the appropriate flag in the "opmask"
1104 * parameter.
1105 */
1106 if (flags & IBT_CEP_SET_QKEY) {
1107 qpc->qkey = ud->ud_qkey;
1108 opmask |= TAVOR_CMD_OP_QKEY;
1109 }
1110
1111 } else if (qp->qp_serv_type == TAVOR_QP_RC) {
1112 rc = &info_p->qp_transport.rc;
1113
1114 /*
1115 * If we are attempting to modify the port for this QP, then
1116 * check for valid port number and fill it in. Also set the
1117 * appropriate flag in the "opmask" parameter.
1118 */
1119 if (flags & IBT_CEP_SET_PORT) {
1120 portnum = rc->rc_path.cep_hca_port_num;
1121 if (tavor_portnum_is_valid(state, portnum)) {
1122 qpc->pri_addr_path.portnum = portnum;
1123 } else {
1124 TNF_PROBE_1(tavor_qp_init2init_inv_port_fail,
1125 TAVOR_TNF_ERROR, "", tnf_uint, port,
1126 portnum);
1127 TAVOR_TNF_EXIT(tavor_qp_init2init);
1128 return (IBT_HCA_PORT_INVALID);
1129 }
1130 opmask |= TAVOR_CMD_OP_PRIM_PORT;
1131 }
1132
1133 /*
1134 * If we are attempting to modify the PKey index for this QP,
1135 * then check for valid PKey index and fill it in. Also set
1136 * the appropriate flag in the "opmask" parameter.
1137 */
1138 if (flags & IBT_CEP_SET_PKEY_IX) {
1139 pkeyindx = rc->rc_path.cep_pkey_ix;
1140 if (tavor_pkeyindex_is_valid(state, pkeyindx)) {
1141 qpc->pri_addr_path.pkey_indx = pkeyindx;
1142 opmask |= TAVOR_CMD_OP_PKEYINDX;
1143 } else {
1144 TNF_PROBE_1(tavor_qp_init2init_inv_pkey_fail,
1145 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx,
1146 pkeyindx);
1147 TAVOR_TNF_EXIT(tavor_qp_init2init);
1148 return (IBT_PKEY_IX_ILLEGAL);
1149 }
1150 }
1151
1152 /*
1153 * Check if any of the flags indicate a change in the RDMA
1154 * (recv) enable/disable flags and set the appropriate flag in
1155 * the "opmask" parameter
1156 */
1157 opmask |= tavor_check_rdma_enable_flags(flags, info_p, qpc);
1158
1159 } else if (qp->qp_serv_type == TAVOR_QP_UC) {
1160 uc = &info_p->qp_transport.uc;
1161
1162 /*
1163 * If we are attempting to modify the port for this QP, then
1164 * check for valid port number and fill it in. Also set the
1165 * appropriate flag in the "opmask" parameter.
1166 */
1167 if (flags & IBT_CEP_SET_PORT) {
1168 portnum = uc->uc_path.cep_hca_port_num;
1169 if (tavor_portnum_is_valid(state, portnum)) {
1170 qpc->pri_addr_path.portnum = portnum;
1171 } else {
1172 TNF_PROBE_1(tavor_qp_init2init_inv_port_fail,
1173 TAVOR_TNF_ERROR, "", tnf_uint, port,
1174 portnum);
1175 TAVOR_TNF_EXIT(tavor_qp_init2init);
1176 return (IBT_HCA_PORT_INVALID);
1177 }
1178 opmask |= TAVOR_CMD_OP_PRIM_PORT;
1179 }
1180
1181 /*
1182 * If we are attempting to modify the PKey index for this QP,
1183 * then check for valid PKey index and fill it in. Also set
1184 * the appropriate flag in the "opmask" parameter.
1185 */
1186 if (flags & IBT_CEP_SET_PKEY_IX) {
1187 pkeyindx = uc->uc_path.cep_pkey_ix;
1188 if (tavor_pkeyindex_is_valid(state, pkeyindx)) {
1189 qpc->pri_addr_path.pkey_indx = pkeyindx;
1190 opmask |= TAVOR_CMD_OP_PKEYINDX;
1191 } else {
1192 TNF_PROBE_1(tavor_qp_init2init_inv_pkey_fail,
1193 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx,
1194 pkeyindx);
1195 TAVOR_TNF_EXIT(tavor_qp_init2init);
1196 return (IBT_PKEY_IX_ILLEGAL);
1197 }
1198 }
1199
1200 /*
1201 * Check if any of the flags indicate a change in the RDMA
1202 * Write (recv) enable/disable and set the appropriate flag
1203 * in the "opmask" parameter. Note: RDMA Read and Atomic are
1204 * not valid for UC transport.
1205 */
1206 if (flags & IBT_CEP_SET_RDMA_W) {
1207 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
1208 opmask |= TAVOR_CMD_OP_RWE;
1209 }
1210 } else {
1211 /*
1212 * Invalid QP transport type. If we got here then it's a
1213 * warning of a probably serious problem. So print a message
1214 * and return failure
1215 */
1216 TAVOR_WARNING(state, "unknown QP transport type in init2init");
1217 TNF_PROBE_0(tavor_qp_init2init_inv_transtype_fail,
1218 TAVOR_TNF_ERROR, "");
1219 TAVOR_TNF_EXIT(tavor_qp_init2init);
1220 return (ibc_get_ci_failure(0));
1221 }
1222
1223 /*
1224 * Post the INIT2INIT_QP command to the Tavor firmware
1225 *
1226 * We do a TAVOR_NOSLEEP here because we are still holding the
1227 * "qp_lock". If we got raised to interrupt level by priority
1228 * inversion, we do not want to block in this routine waiting for
1229 * success.
1230 */
1231 status = tavor_cmn_qp_cmd_post(state, INIT2INIT_QP, qpc, qp->qp_qpnum,
1232 opmask, TAVOR_CMD_NOSLEEP_SPIN);
1233 if (status != TAVOR_CMD_SUCCESS) {
1234 if (status != TAVOR_CMD_BAD_QP_STATE) {
1235 cmn_err(CE_CONT, "Tavor: INIT2INIT_QP command failed: "
1236 "%08x\n", status);
1237 TNF_PROBE_1(tavor_qp_init2init_cmd_fail,
1238 TAVOR_TNF_ERROR, "", tnf_uint, status, status);
1239 TAVOR_TNF_EXIT(tavor_qp_init2init);
1240 return (ibc_get_ci_failure(0));
1241 } else {
1242 TNF_PROBE_0(tavor_qp_init2init_inv_qpstate_fail,
1243 TAVOR_TNF_ERROR, "");
1244 TAVOR_TNF_EXIT(tavor_qp_init2init);
1245 return (IBT_QP_STATE_INVALID);
1246 }
1247 }
1248
1249 TAVOR_TNF_EXIT(tavor_qp_init2init);
1250 return (DDI_SUCCESS);
1251 }
1252
1253
1254 /*
1255 * tavor_qp_init2rtr()
1256 * Context: Can be called from interrupt or base context.
1257 */
1258 static int
tavor_qp_init2rtr(tavor_state_t * state,tavor_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p)1259 tavor_qp_init2rtr(tavor_state_t *state, tavor_qphdl_t qp,
1260 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p)
1261 {
1262 tavor_hw_qpc_t *qpc;
1263 ibt_qp_rc_attr_t *rc;
1264 ibt_qp_ud_attr_t *ud;
1265 ibt_qp_uc_attr_t *uc;
1266 tavor_hw_addr_path_t *qpc_path;
1267 ibt_adds_vect_t *adds_vect;
1268 uint_t portnum, pkeyindx, rdma_ra_in, rra_max;
1269 uint_t mtu;
1270 uint32_t opmask = 0;
1271 int status;
1272
1273 TAVOR_TNF_ENTER(tavor_qp_init2rtr);
1274
1275 ASSERT(MUTEX_HELD(&qp->qp_lock));
1276
1277 /*
1278 * Grab the temporary QPC entry from QP software state
1279 */
1280 qpc = &qp->qpc;
1281
1282 /*
1283 * Since there are no common and/or Tavor-specific fields to be filled
1284 * in for this command, we begin with the QPC fields which are
1285 * specific to transport type.
1286 */
1287 if (qp->qp_serv_type == TAVOR_QP_UD) {
1288 ud = &info_p->qp_transport.ud;
1289
1290 /*
1291 * If this UD QP is also a "special QP" (QP0 or QP1), then
1292 * the MTU is 256 bytes. However, Tavor HW requires us to
1293 * set the MTU to 4 (which is the IB code for a 2K MTU).
1294 * If this is not a special QP, then we set the MTU to the
1295 * configured maximum (which defaults to 2K). Note: the
1296 * QPC "msg_max" must also be set so as to correspond with
1297 * the specified MTU value.
1298 */
1299 if (qp->qp_is_special) {
1300 qpc->mtu = 4;
1301 } else {
1302 qpc->mtu = state->ts_cfg_profile->cp_max_mtu;
1303 }
1304 qpc->msg_max = qpc->mtu + 7; /* must equal MTU plus seven */
1305
1306 /*
1307 * Save away the MTU value. This is used in future sqd2sqd
1308 * transitions, as the MTU must remain the same in future
1309 * changes.
1310 */
1311 qp->qp_save_mtu = qpc->mtu;
1312
1313 /*
1314 * If we are attempting to modify the PKey index for this QP,
1315 * then check for valid PKey index and fill it in. Also set
1316 * the appropriate flag in the "opmask" parameter.
1317 */
1318 if (flags & IBT_CEP_SET_PKEY_IX) {
1319 pkeyindx = ud->ud_pkey_ix;
1320 if (tavor_pkeyindex_is_valid(state, pkeyindx)) {
1321 qpc->pri_addr_path.pkey_indx = pkeyindx;
1322 opmask |= TAVOR_CMD_OP_PKEYINDX;
1323 qp->qp_pkeyindx = pkeyindx;
1324 } else {
1325 TNF_PROBE_1(tavor_qp_init2rtr_inv_pkey_fail,
1326 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx,
1327 pkeyindx);
1328 TAVOR_TNF_EXIT(tavor_qp_init2rtr);
1329 return (IBT_PKEY_IX_ILLEGAL);
1330 }
1331 }
1332
1333 /*
1334 * If we are attempting to modify the QKey for this QP, then
1335 * fill it in and set the appropriate flag in the "opmask"
1336 * parameter.
1337 */
1338 if (flags & IBT_CEP_SET_QKEY) {
1339 qpc->qkey = ud->ud_qkey;
1340 opmask |= TAVOR_CMD_OP_QKEY;
1341 }
1342
1343 } else if (qp->qp_serv_type == TAVOR_QP_RC) {
1344 rc = &info_p->qp_transport.rc;
1345 qpc_path = &qpc->pri_addr_path;
1346 adds_vect = &rc->rc_path.cep_adds_vect;
1347
1348 /*
1349 * Set the common primary address path fields
1350 */
1351 status = tavor_set_addr_path(state, adds_vect, qpc_path,
1352 TAVOR_ADDRPATH_QP, qp);
1353 if (status != DDI_SUCCESS) {
1354 TNF_PROBE_0(tavor_qp_init2rtr_setaddrpath_fail,
1355 TAVOR_TNF_ERROR, "");
1356 TAVOR_TNF_EXIT(tavor_qp_init2rtr);
1357 return (status);
1358 }
1359
1360 /*
1361 * The following values are apparently "required" here (as
1362 * they are part of the IBA-defined "Remote Node Address
1363 * Vector"). However, they are also going to be "required"
1364 * later - at RTR2RTS_QP time. Not sure why. But we set
1365 * them here anyway.
1366 */
1367 qpc_path->rnr_retry = rc->rc_rnr_retry_cnt;
1368 qpc->retry_cnt = rc->rc_retry_cnt;
1369 qpc_path->ack_timeout = rc->rc_path.cep_timeout;
1370
1371 /*
1372 * Setup the destination QP, recv PSN, MTU, max msg size,etc.
1373 * Note max message size is defined to be the maximum IB
1374 * allowed message size (which is 2^31 bytes). Also max
1375 * MTU is defined by HCA port properties.
1376 */
1377 qpc->rem_qpn = rc->rc_dst_qpn;
1378 qpc->next_rcv_psn = rc->rc_rq_psn;
1379 qpc->msg_max = TAVOR_QP_LOG_MAX_MSGSZ;
1380
1381 /*
1382 * If this QP is using an SRQ, 'ric' must be set to 1.
1383 */
1384 qpc->ric = (qp->qp_srq_en == TAVOR_QP_SRQ_ENABLED) ? 1 : 0;
1385 mtu = rc->rc_path_mtu;
1386 if (tavor_qp_validate_mtu(state, mtu) != DDI_SUCCESS) {
1387 TNF_PROBE_1(tavor_qp_init2rtr_inv_mtu_fail,
1388 TAVOR_TNF_ERROR, "", tnf_uint, mtu, mtu);
1389 TAVOR_TNF_EXIT(tavor_qp_init2rtr);
1390 return (IBT_HCA_PORT_MTU_EXCEEDED);
1391 }
1392 qpc->mtu = mtu;
1393
1394 /*
1395 * Save away the MTU value. This is used in future sqd2sqd
1396 * transitions, as the MTU must remain the same in future
1397 * changes.
1398 */
1399 qp->qp_save_mtu = qpc->mtu;
1400
1401 /*
1402 * Though it is a "required" parameter, "min_rnr_nak" is
1403 * optionally specifiable in Tavor. So we hardcode the
1404 * optional flag here.
1405 */
1406 qpc->min_rnr_nak = rc->rc_min_rnr_nak;
1407 opmask |= TAVOR_CMD_OP_MINRNRNAK;
1408
1409 /*
1410 * Check that the number of specified "incoming RDMA resources"
1411 * is valid. And if it is, then setup the "rra_max" and
1412 * "ra_buf_index" fields in the QPC to point to the
1413 * pre-allocated RDB resources (in DDR)
1414 */
1415 rdma_ra_in = rc->rc_rdma_ra_in;
1416 if (tavor_qp_validate_resp_rsrc(state, rc, &rra_max) !=
1417 DDI_SUCCESS) {
1418 TNF_PROBE_1(tavor_qp_init2rtr_inv_rdma_in_fail,
1419 TAVOR_TNF_ERROR, "", tnf_uint, rdma_ra_in,
1420 rdma_ra_in);
1421 TAVOR_TNF_EXIT(tavor_qp_init2rtr);
1422 return (IBT_INVALID_PARAM);
1423 }
1424 qpc->rra_max = rra_max;
1425 qpc->ra_buff_indx = qp->qp_rdb_ddraddr >> TAVOR_RDB_SIZE_SHIFT;
1426
1427 /*
1428 * If we are attempting to modify the PKey index for this QP,
1429 * then check for valid PKey index and fill it in. Also set
1430 * the appropriate flag in the "opmask" parameter.
1431 */
1432 if (flags & IBT_CEP_SET_PKEY_IX) {
1433 pkeyindx = rc->rc_path.cep_pkey_ix;
1434 if (tavor_pkeyindex_is_valid(state, pkeyindx)) {
1435 qpc->pri_addr_path.pkey_indx = pkeyindx;
1436 opmask |= TAVOR_CMD_OP_PKEYINDX;
1437 } else {
1438 TNF_PROBE_1(tavor_qp_init2rtr_inv_pkey_fail,
1439 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx,
1440 pkeyindx);
1441 TAVOR_TNF_EXIT(tavor_qp_init2rtr);
1442 return (IBT_PKEY_IX_ILLEGAL);
1443 }
1444 }
1445
1446 /*
1447 * Check if any of the flags indicate a change in the RDMA
1448 * (recv) enable/disable flags and set the appropriate flag in
1449 * the "opmask" parameter
1450 */
1451 opmask |= tavor_check_rdma_enable_flags(flags, info_p, qpc);
1452
1453 /*
1454 * Check for optional alternate path and fill in the
1455 * appropriate QPC fields if one is specified
1456 */
1457 if (flags & IBT_CEP_SET_ALT_PATH) {
1458 qpc_path = &qpc->alt_addr_path;
1459 adds_vect = &rc->rc_alt_path.cep_adds_vect;
1460
1461 /* Set the common alternate address path fields */
1462 status = tavor_set_addr_path(state, adds_vect, qpc_path,
1463 TAVOR_ADDRPATH_QP, qp);
1464 if (status != DDI_SUCCESS) {
1465 TNF_PROBE_0(tavor_qp_init2rtr_setaddrpath_fail,
1466 TAVOR_TNF_ERROR, "");
1467 TAVOR_TNF_EXIT(tavor_qp_init2rtr);
1468 return (status);
1469 }
1470 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
1471
1472 /*
1473 * Copy the "RNR Retry count" value from the primary
1474 * path. Just as we did above, we need to hardcode
1475 * the optional flag here (see below).
1476 */
1477 qpc_path->rnr_retry = rc->rc_rnr_retry_cnt;
1478
1479 /*
1480 * Check for valid alternate path port number and fill
1481 * it in
1482 */
1483 portnum = rc->rc_alt_path.cep_hca_port_num;
1484 if (tavor_portnum_is_valid(state, portnum)) {
1485 qpc->alt_addr_path.portnum = portnum;
1486 } else {
1487 TNF_PROBE_1(tavor_qp_init2rtr_inv_altport_fail,
1488 TAVOR_TNF_ERROR, "", tnf_uint, altport,
1489 portnum);
1490 TAVOR_TNF_EXIT(tavor_qp_init2rtr);
1491 return (IBT_HCA_PORT_INVALID);
1492 }
1493
1494 /*
1495 * Check for valid alternate path PKey index and fill
1496 * it in
1497 */
1498 pkeyindx = rc->rc_alt_path.cep_pkey_ix;
1499 if (tavor_pkeyindex_is_valid(state, pkeyindx)) {
1500 qpc->alt_addr_path.pkey_indx = pkeyindx;
1501 } else {
1502 TNF_PROBE_1(tavor_qp_init2rtr_inv_altpkey_fail,
1503 TAVOR_TNF_ERROR, "", tnf_uint, altpkeyindx,
1504 pkeyindx);
1505 TAVOR_TNF_EXIT(tavor_qp_init2rtr);
1506 return (IBT_PKEY_IX_ILLEGAL);
1507 }
1508 opmask |= (TAVOR_CMD_OP_ALT_PATH |
1509 TAVOR_CMD_OP_ALT_RNRRETRY);
1510 }
1511
1512 } else if (qp->qp_serv_type == TAVOR_QP_UC) {
1513 uc = &info_p->qp_transport.uc;
1514 qpc_path = &qpc->pri_addr_path;
1515 adds_vect = &uc->uc_path.cep_adds_vect;
1516
1517 /*
1518 * Set the common primary address path fields
1519 */
1520 status = tavor_set_addr_path(state, adds_vect, qpc_path,
1521 TAVOR_ADDRPATH_QP, qp);
1522 if (status != DDI_SUCCESS) {
1523 TNF_PROBE_0(tavor_qp_init2rtr_setaddrpath_fail,
1524 TAVOR_TNF_ERROR, "");
1525 TAVOR_TNF_EXIT(tavor_qp_init2rtr);
1526 return (status);
1527 }
1528
1529 /*
1530 * Setup the destination QP, recv PSN, MTU, max msg size,etc.
1531 * Note max message size is defined to be the maximum IB
1532 * allowed message size (which is 2^31 bytes). Also max
1533 * MTU is defined by HCA port properties.
1534 */
1535 qpc->rem_qpn = uc->uc_dst_qpn;
1536 qpc->next_rcv_psn = uc->uc_rq_psn;
1537 qpc->msg_max = TAVOR_QP_LOG_MAX_MSGSZ;
1538 mtu = uc->uc_path_mtu;
1539 if (tavor_qp_validate_mtu(state, mtu) != DDI_SUCCESS) {
1540 TNF_PROBE_1(tavor_qp_init2rtr_inv_mtu_fail,
1541 TAVOR_TNF_ERROR, "", tnf_uint, mtu, mtu);
1542 TAVOR_TNF_EXIT(tavor_qp_init2rtr);
1543 return (IBT_HCA_PORT_MTU_EXCEEDED);
1544 }
1545 qpc->mtu = mtu;
1546
1547 /*
1548 * Save away the MTU value. This is used in future sqd2sqd
1549 * transitions, as the MTU must remain the same in future
1550 * changes.
1551 */
1552 qp->qp_save_mtu = qpc->mtu;
1553
1554 /*
1555 * If we are attempting to modify the PKey index for this QP,
1556 * then check for valid PKey index and fill it in. Also set
1557 * the appropriate flag in the "opmask" parameter.
1558 */
1559 if (flags & IBT_CEP_SET_PKEY_IX) {
1560 pkeyindx = uc->uc_path.cep_pkey_ix;
1561 if (tavor_pkeyindex_is_valid(state, pkeyindx)) {
1562 qpc->pri_addr_path.pkey_indx = pkeyindx;
1563 opmask |= TAVOR_CMD_OP_PKEYINDX;
1564 } else {
1565 TNF_PROBE_1(tavor_qp_init2rtr_inv_pkey_fail,
1566 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx,
1567 pkeyindx);
1568 TAVOR_TNF_EXIT(tavor_qp_init2rtr);
1569 return (IBT_PKEY_IX_ILLEGAL);
1570 }
1571 }
1572
1573 /*
1574 * Check if any of the flags indicate a change in the RDMA
1575 * Write (recv) enable/disable and set the appropriate flag
1576 * in the "opmask" parameter. Note: RDMA Read and Atomic are
1577 * not valid for UC transport.
1578 */
1579 if (flags & IBT_CEP_SET_RDMA_W) {
1580 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
1581 opmask |= TAVOR_CMD_OP_RWE;
1582 }
1583
1584 /*
1585 * Check for optional alternate path and fill in the
1586 * appropriate QPC fields if one is specified
1587 */
1588 if (flags & IBT_CEP_SET_ALT_PATH) {
1589 qpc_path = &qpc->alt_addr_path;
1590 adds_vect = &uc->uc_alt_path.cep_adds_vect;
1591
1592 /* Set the common alternate address path fields */
1593 status = tavor_set_addr_path(state, adds_vect, qpc_path,
1594 TAVOR_ADDRPATH_QP, qp);
1595 if (status != DDI_SUCCESS) {
1596 TNF_PROBE_0(tavor_qp_init2rtr_setaddrpath_fail,
1597 TAVOR_TNF_ERROR, "");
1598 TAVOR_TNF_EXIT(tavor_qp_init2rtr);
1599 return (status);
1600 }
1601
1602 /*
1603 * Check for valid alternate path port number and fill
1604 * it in
1605 */
1606 portnum = uc->uc_alt_path.cep_hca_port_num;
1607 if (tavor_portnum_is_valid(state, portnum)) {
1608 qpc->alt_addr_path.portnum = portnum;
1609 } else {
1610 TNF_PROBE_1(tavor_qp_init2rtr_inv_altport_fail,
1611 TAVOR_TNF_ERROR, "", tnf_uint, altport,
1612 portnum);
1613 TAVOR_TNF_EXIT(tavor_qp_init2rtr);
1614 return (IBT_HCA_PORT_INVALID);
1615 }
1616
1617 /*
1618 * Check for valid alternate path PKey index and fill
1619 * it in
1620 */
1621 pkeyindx = uc->uc_alt_path.cep_pkey_ix;
1622 if (tavor_pkeyindex_is_valid(state, pkeyindx)) {
1623 qpc->alt_addr_path.pkey_indx = pkeyindx;
1624 } else {
1625 TNF_PROBE_1(tavor_qp_init2rtr_inv_altpkey_fail,
1626 TAVOR_TNF_ERROR, "", tnf_uint, altpkeyindx,
1627 pkeyindx);
1628 TAVOR_TNF_EXIT(tavor_qp_init2rtr);
1629 return (IBT_PKEY_IX_ILLEGAL);
1630 }
1631 opmask |= TAVOR_CMD_OP_ALT_PATH;
1632 }
1633 } else {
1634 /*
1635 * Invalid QP transport type. If we got here then it's a
1636 * warning of a probably serious problem. So print a message
1637 * and return failure
1638 */
1639 TAVOR_WARNING(state, "unknown QP transport type in init2rtr");
1640 TNF_PROBE_0(tavor_qp_init2rtr_inv_transtype_fail,
1641 TAVOR_TNF_ERROR, "");
1642 TAVOR_TNF_EXIT(tavor_qp_init2rtr);
1643 return (ibc_get_ci_failure(0));
1644 }
1645
1646 /*
1647 * Post the INIT2RTR_QP command to the Tavor firmware
1648 *
1649 * We do a TAVOR_NOSLEEP here because we are still holding the
1650 * "qp_lock". If we got raised to interrupt level by priority
1651 * inversion, we do not want to block in this routine waiting for
1652 * success.
1653 */
1654 status = tavor_cmn_qp_cmd_post(state, INIT2RTR_QP, qpc, qp->qp_qpnum,
1655 opmask, TAVOR_CMD_NOSLEEP_SPIN);
1656 if (status != TAVOR_CMD_SUCCESS) {
1657 if (status != TAVOR_CMD_BAD_QP_STATE) {
1658 cmn_err(CE_CONT, "Tavor: INIT2RTR_QP command failed: "
1659 "%08x\n", status);
1660 TNF_PROBE_1(tavor_qp_init2rtr_cmd_fail,
1661 TAVOR_TNF_ERROR, "", tnf_uint, status, status);
1662 TAVOR_TNF_EXIT(tavor_qp_init2rtr);
1663 return (ibc_get_ci_failure(0));
1664 } else {
1665 TNF_PROBE_0(tavor_qp_init2rtr_inv_qpstate_fail,
1666 TAVOR_TNF_ERROR, "");
1667 TAVOR_TNF_EXIT(tavor_qp_init2rtr);
1668 return (IBT_QP_STATE_INVALID);
1669 }
1670 }
1671
1672 TAVOR_TNF_EXIT(tavor_qp_init2rtr);
1673 return (DDI_SUCCESS);
1674 }
1675
1676
1677 /*
1678 * tavor_qp_rtr2rts()
1679 * Context: Can be called from interrupt or base context.
1680 */
1681 static int
tavor_qp_rtr2rts(tavor_state_t * state,tavor_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p)1682 tavor_qp_rtr2rts(tavor_state_t *state, tavor_qphdl_t qp,
1683 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p)
1684 {
1685 tavor_hw_qpc_t *qpc;
1686 ibt_qp_rc_attr_t *rc;
1687 ibt_qp_ud_attr_t *ud;
1688 ibt_qp_uc_attr_t *uc;
1689 tavor_hw_addr_path_t *qpc_path;
1690 ibt_adds_vect_t *adds_vect;
1691 uint_t portnum, pkeyindx, rdma_ra_out, sra_max;
1692 uint32_t opmask = 0;
1693 int status;
1694
1695 TAVOR_TNF_ENTER(tavor_qp_rtr2rts);
1696
1697 ASSERT(MUTEX_HELD(&qp->qp_lock));
1698
1699 /*
1700 * Grab the temporary QPC entry from QP software state
1701 */
1702 qpc = &qp->qpc;
1703
1704 /*
1705 * Fill in the common and/or Tavor-specific fields in the QPC
1706 */
1707 qpc->flight_lim = TAVOR_QP_FLIGHT_LIM_UNLIMITED;
1708
1709 /*
1710 * Now fill in the QPC fields which are specific to transport type
1711 */
1712 if (qp->qp_serv_type == TAVOR_QP_UD) {
1713 ud = &info_p->qp_transport.ud;
1714
1715 /* Set the send PSN */
1716 qpc->next_snd_psn = ud->ud_sq_psn;
1717
1718 /*
1719 * If we are attempting to modify the QKey for this QP, then
1720 * fill it in and set the appropriate flag in the "opmask"
1721 * parameter.
1722 */
1723 if (flags & IBT_CEP_SET_QKEY) {
1724 qpc->qkey = ud->ud_qkey;
1725 opmask |= TAVOR_CMD_OP_QKEY;
1726 }
1727
1728 } else if (qp->qp_serv_type == TAVOR_QP_RC) {
1729 rc = &info_p->qp_transport.rc;
1730 qpc_path = &qpc->pri_addr_path;
1731
1732 /*
1733 * Setup the send PSN, ACK timeout, and retry counts
1734 */
1735 qpc->next_snd_psn = rc->rc_sq_psn;
1736 qpc_path->ack_timeout = rc->rc_path.cep_timeout;
1737 qpc_path->rnr_retry = rc->rc_rnr_retry_cnt;
1738 qpc->retry_cnt = rc->rc_retry_cnt;
1739
1740 /*
1741 * Set "ack_req_freq" based on the configuration variable
1742 */
1743 qpc->ack_req_freq = state->ts_cfg_profile->cp_ackreq_freq;
1744
1745 /*
1746 * Check that the number of specified "outgoing RDMA resources"
1747 * is valid. And if it is, then setup the "sra_max"
1748 * appropriately
1749 */
1750 rdma_ra_out = rc->rc_rdma_ra_out;
1751 if (tavor_qp_validate_init_depth(state, rc, &sra_max) !=
1752 DDI_SUCCESS) {
1753 TNF_PROBE_1(tavor_qp_rtr2rts_inv_rdma_out_fail,
1754 TAVOR_TNF_ERROR, "", tnf_uint, rdma_ra_out,
1755 rdma_ra_out);
1756 TAVOR_TNF_EXIT(tavor_qp_rtr2rts);
1757 return (IBT_INVALID_PARAM);
1758 }
1759 qpc->sra_max = sra_max;
1760
1761 /*
1762 * Configure the QP to allow (sending of) all types of RC
1763 * traffic. Tavor hardware allows these bits to be set to
1764 * zero (thereby disabling certain outgoing RDMA types), but
1765 * we do not desire to do this.
1766 */
1767 qpc->sre = qpc->swe = qpc->sae = 1;
1768 qpc->sic = 0;
1769
1770 /*
1771 * Check if any of the flags indicate a change in the RDMA
1772 * (recv) enable/disable flags and set the appropriate flag in
1773 * the "opmask" parameter
1774 */
1775 opmask |= tavor_check_rdma_enable_flags(flags, info_p, qpc);
1776
1777 /*
1778 * If we are attempting to modify the path migration state for
1779 * this QP, then check for valid state and fill it in. Also
1780 * set the appropriate flag in the "opmask" parameter.
1781 */
1782 if (flags & IBT_CEP_SET_MIG) {
1783 if (rc->rc_mig_state == IBT_STATE_MIGRATED) {
1784 qpc->pm_state = TAVOR_QP_PMSTATE_MIGRATED;
1785 } else if (rc->rc_mig_state == IBT_STATE_REARMED) {
1786 qpc->pm_state = TAVOR_QP_PMSTATE_REARM;
1787 } else {
1788 TNF_PROBE_1(tavor_qp_rtr2rts_inv_mig_state_fail,
1789 TAVOR_TNF_ERROR, "", tnf_uint, mig_state,
1790 rc->rc_mig_state);
1791 TAVOR_TNF_EXIT(tavor_qp_rtr2rts);
1792 return (IBT_QP_APM_STATE_INVALID);
1793 }
1794 opmask |= TAVOR_CMD_OP_PM_STATE;
1795 }
1796
1797 /*
1798 * If we are attempting to modify the "Minimum RNR NAK" value
1799 * for this QP, then fill it in and set the appropriate flag
1800 * in the "opmask" parameter.
1801 */
1802 if (flags & IBT_CEP_SET_MIN_RNR_NAK) {
1803 qpc->min_rnr_nak = rc->rc_min_rnr_nak;
1804 opmask |= TAVOR_CMD_OP_MINRNRNAK;
1805 }
1806
1807 /*
1808 * Check for optional alternate path and fill in the
1809 * appropriate QPC fields if one is specified
1810 */
1811 if (flags & IBT_CEP_SET_ALT_PATH) {
1812 qpc_path = &qpc->alt_addr_path;
1813 adds_vect = &rc->rc_alt_path.cep_adds_vect;
1814
1815 /* Set the common alternate address path fields */
1816 status = tavor_set_addr_path(state, adds_vect, qpc_path,
1817 TAVOR_ADDRPATH_QP, qp);
1818 if (status != DDI_SUCCESS) {
1819 TNF_PROBE_0(tavor_qp_rtr2rts_setaddrpath_fail,
1820 TAVOR_TNF_ERROR, "");
1821 TAVOR_TNF_EXIT(tavor_qp_rtr2rts);
1822 return (status);
1823 }
1824
1825 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
1826
1827 /*
1828 * Copy the "RNR Retry count" value from the primary
1829 * path. Just as we did above, we need to hardcode
1830 * the optional flag here (see below).
1831 */
1832 qpc_path->rnr_retry = rc->rc_rnr_retry_cnt;
1833
1834 /*
1835 * Check for valid alternate path port number and fill
1836 * it in
1837 */
1838 portnum = rc->rc_alt_path.cep_hca_port_num;
1839 if (tavor_portnum_is_valid(state, portnum)) {
1840 qpc->alt_addr_path.portnum = portnum;
1841 } else {
1842 TNF_PROBE_1(tavor_qp_rtr2rts_inv_altport_fail,
1843 TAVOR_TNF_ERROR, "", tnf_uint, altport,
1844 portnum);
1845 TAVOR_TNF_EXIT(tavor_qp_rtr2rts);
1846 return (IBT_HCA_PORT_INVALID);
1847 }
1848
1849 /*
1850 * Check for valid alternate path PKey index and fill
1851 * it in
1852 */
1853 pkeyindx = rc->rc_alt_path.cep_pkey_ix;
1854 if (tavor_pkeyindex_is_valid(state, pkeyindx)) {
1855 qpc->alt_addr_path.pkey_indx = pkeyindx;
1856 } else {
1857 TNF_PROBE_1(tavor_qp_rtr2rts_inv_altpkey_fail,
1858 TAVOR_TNF_ERROR, "", tnf_uint, altpkeyindx,
1859 pkeyindx);
1860 TAVOR_TNF_EXIT(tavor_qp_rtr2rts);
1861 return (IBT_PKEY_IX_ILLEGAL);
1862 }
1863 opmask |= (TAVOR_CMD_OP_ALT_PATH |
1864 TAVOR_CMD_OP_ALT_RNRRETRY);
1865 }
1866
1867 } else if (qp->qp_serv_type == TAVOR_QP_UC) {
1868 uc = &info_p->qp_transport.uc;
1869
1870 /* Set the send PSN */
1871 qpc->next_snd_psn = uc->uc_sq_psn;
1872
1873 /*
1874 * Configure the QP to allow (sending of) all types of allowable
1875 * UC traffic (i.e. RDMA Write).
1876 */
1877 qpc->swe = 1;
1878
1879 /*
1880 * Check if any of the flags indicate a change in the RDMA
1881 * Write (recv) enable/disable and set the appropriate flag
1882 * in the "opmask" parameter. Note: RDMA Read and Atomic are
1883 * not valid for UC transport.
1884 */
1885 if (flags & IBT_CEP_SET_RDMA_W) {
1886 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
1887 opmask |= TAVOR_CMD_OP_RWE;
1888 }
1889
1890 /*
1891 * If we are attempting to modify the path migration state for
1892 * this QP, then check for valid state and fill it in. Also
1893 * set the appropriate flag in the "opmask" parameter.
1894 */
1895 if (flags & IBT_CEP_SET_MIG) {
1896 if (uc->uc_mig_state == IBT_STATE_MIGRATED) {
1897 qpc->pm_state = TAVOR_QP_PMSTATE_MIGRATED;
1898 } else if (uc->uc_mig_state == IBT_STATE_REARMED) {
1899 qpc->pm_state = TAVOR_QP_PMSTATE_REARM;
1900 } else {
1901 TNF_PROBE_1(tavor_qp_rtr2rts_inv_mig_state_fail,
1902 TAVOR_TNF_ERROR, "", tnf_uint, mig_state,
1903 uc->uc_mig_state);
1904 TAVOR_TNF_EXIT(tavor_qp_rtr2rts);
1905 return (IBT_QP_APM_STATE_INVALID);
1906 }
1907 opmask |= TAVOR_CMD_OP_PM_STATE;
1908 }
1909
1910 /*
1911 * Check for optional alternate path and fill in the
1912 * appropriate QPC fields if one is specified
1913 */
1914 if (flags & IBT_CEP_SET_ALT_PATH) {
1915 qpc_path = &qpc->alt_addr_path;
1916 adds_vect = &uc->uc_alt_path.cep_adds_vect;
1917
1918 /* Set the common alternate address path fields */
1919 status = tavor_set_addr_path(state, adds_vect, qpc_path,
1920 TAVOR_ADDRPATH_QP, qp);
1921 if (status != DDI_SUCCESS) {
1922 TNF_PROBE_0(tavor_qp_rtr2rts_setaddrpath_fail,
1923 TAVOR_TNF_ERROR, "");
1924 TAVOR_TNF_EXIT(tavor_qp_rtr2rts);
1925 return (status);
1926 }
1927
1928 /*
1929 * Check for valid alternate path port number and fill
1930 * it in
1931 */
1932 portnum = uc->uc_alt_path.cep_hca_port_num;
1933 if (tavor_portnum_is_valid(state, portnum)) {
1934 qpc->alt_addr_path.portnum = portnum;
1935 } else {
1936 TNF_PROBE_1(tavor_qp_rtr2rts_inv_altport_fail,
1937 TAVOR_TNF_ERROR, "", tnf_uint, altport,
1938 portnum);
1939 TAVOR_TNF_EXIT(tavor_qp_rtr2rts);
1940 return (IBT_HCA_PORT_INVALID);
1941 }
1942
1943 /*
1944 * Check for valid alternate path PKey index and fill
1945 * it in
1946 */
1947 pkeyindx = uc->uc_alt_path.cep_pkey_ix;
1948 if (tavor_pkeyindex_is_valid(state, pkeyindx)) {
1949 qpc->alt_addr_path.pkey_indx = pkeyindx;
1950 } else {
1951 TNF_PROBE_1(tavor_qp_rtr2rts_inv_altpkey_fail,
1952 TAVOR_TNF_ERROR, "", tnf_uint, altpkeyindx,
1953 pkeyindx);
1954 TAVOR_TNF_EXIT(tavor_qp_rtr2rts);
1955 return (IBT_PKEY_IX_ILLEGAL);
1956 }
1957 opmask |= TAVOR_CMD_OP_ALT_PATH;
1958 }
1959 } else {
1960 /*
1961 * Invalid QP transport type. If we got here then it's a
1962 * warning of a probably serious problem. So print a message
1963 * and return failure
1964 */
1965 TAVOR_WARNING(state, "unknown QP transport type in rtr2rts");
1966 TNF_PROBE_0(tavor_qp_rtr2rts_inv_transtype_fail,
1967 TAVOR_TNF_ERROR, "");
1968 TAVOR_TNF_EXIT(tavor_qp_rtr2rts);
1969 return (ibc_get_ci_failure(0));
1970 }
1971
1972 /*
1973 * Post the RTR2RTS_QP command to the Tavor firmware
1974 *
1975 * We do a TAVOR_NOSLEEP here because we are still holding the
1976 * "qp_lock". If we got raised to interrupt level by priority
1977 * inversion, we do not want to block in this routine waiting for
1978 * success.
1979 */
1980 status = tavor_cmn_qp_cmd_post(state, RTR2RTS_QP, qpc, qp->qp_qpnum,
1981 opmask, TAVOR_CMD_NOSLEEP_SPIN);
1982 if (status != TAVOR_CMD_SUCCESS) {
1983 if (status != TAVOR_CMD_BAD_QP_STATE) {
1984 cmn_err(CE_CONT, "Tavor: RTR2RTS_QP command failed: "
1985 "%08x\n", status);
1986 TNF_PROBE_1(tavor_qp_rtr2rts_cmd_fail,
1987 TAVOR_TNF_ERROR, "", tnf_uint, status, status);
1988 TAVOR_TNF_EXIT(tavor_qp_rtr2rts);
1989 return (ibc_get_ci_failure(0));
1990 } else {
1991 TNF_PROBE_0(tavor_qp_rtr2rts_inv_qpstate_fail,
1992 TAVOR_TNF_ERROR, "");
1993 TAVOR_TNF_EXIT(tavor_qp_rtr2rts);
1994 return (IBT_QP_STATE_INVALID);
1995 }
1996 }
1997
1998 TAVOR_TNF_EXIT(tavor_qp_rtr2rts);
1999 return (DDI_SUCCESS);
2000 }
2001
2002
2003 /*
2004 * tavor_qp_rts2rts()
2005 * Context: Can be called from interrupt or base context.
2006 */
2007 static int
tavor_qp_rts2rts(tavor_state_t * state,tavor_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p)2008 tavor_qp_rts2rts(tavor_state_t *state, tavor_qphdl_t qp,
2009 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p)
2010 {
2011 tavor_hw_qpc_t *qpc;
2012 ibt_qp_rc_attr_t *rc;
2013 ibt_qp_ud_attr_t *ud;
2014 ibt_qp_uc_attr_t *uc;
2015 tavor_hw_addr_path_t *qpc_path;
2016 ibt_adds_vect_t *adds_vect;
2017 uint_t portnum, pkeyindx;
2018 uint32_t opmask = 0;
2019 int status;
2020
2021 TAVOR_TNF_ENTER(tavor_qp_rts2rts);
2022
2023 ASSERT(MUTEX_HELD(&qp->qp_lock));
2024
2025 /*
2026 * Grab the temporary QPC entry from QP software state
2027 */
2028 qpc = &qp->qpc;
2029
2030 /*
2031 * Since there are no common and/or Tavor-specific fields to be filled
2032 * in for this command, we begin with the QPC fields which are
2033 * specific to transport type.
2034 */
2035 if (qp->qp_serv_type == TAVOR_QP_UD) {
2036 ud = &info_p->qp_transport.ud;
2037
2038 /*
2039 * If we are attempting to modify the QKey for this QP, then
2040 * fill it in and set the appropriate flag in the "opmask"
2041 * parameter.
2042 */
2043 if (flags & IBT_CEP_SET_QKEY) {
2044 qpc->qkey = ud->ud_qkey;
2045 opmask |= TAVOR_CMD_OP_QKEY;
2046 }
2047
2048 } else if (qp->qp_serv_type == TAVOR_QP_RC) {
2049 rc = &info_p->qp_transport.rc;
2050
2051 /*
2052 * Check if any of the flags indicate a change in the RDMA
2053 * (recv) enable/disable flags and set the appropriate flag in
2054 * the "opmask" parameter
2055 */
2056 opmask |= tavor_check_rdma_enable_flags(flags, info_p, qpc);
2057
2058 /*
2059 * If we are attempting to modify the path migration state for
2060 * this QP, then check for valid state and fill it in. Also
2061 * set the appropriate flag in the "opmask" parameter.
2062 */
2063 if (flags & IBT_CEP_SET_MIG) {
2064 if (rc->rc_mig_state == IBT_STATE_MIGRATED) {
2065 qpc->pm_state = TAVOR_QP_PMSTATE_MIGRATED;
2066 } else if (rc->rc_mig_state == IBT_STATE_REARMED) {
2067 qpc->pm_state = TAVOR_QP_PMSTATE_REARM;
2068 } else {
2069 TNF_PROBE_1(tavor_qp_rts2rts_inv_mig_state_fail,
2070 TAVOR_TNF_ERROR, "", tnf_uint, mig_state,
2071 rc->rc_mig_state);
2072 TAVOR_TNF_EXIT(tavor_qp_rts2rts);
2073 return (IBT_QP_APM_STATE_INVALID);
2074 }
2075 opmask |= TAVOR_CMD_OP_PM_STATE;
2076 }
2077
2078 /*
2079 * If we are attempting to modify the "Minimum RNR NAK" value
2080 * for this QP, then fill it in and set the appropriate flag
2081 * in the "opmask" parameter.
2082 */
2083 if (flags & IBT_CEP_SET_MIN_RNR_NAK) {
2084 qpc->min_rnr_nak = rc->rc_min_rnr_nak;
2085 opmask |= TAVOR_CMD_OP_MINRNRNAK;
2086 }
2087
2088 /*
2089 * Check for optional alternate path and fill in the
2090 * appropriate QPC fields if one is specified
2091 */
2092 if (flags & IBT_CEP_SET_ALT_PATH) {
2093 qpc_path = &qpc->alt_addr_path;
2094 adds_vect = &rc->rc_alt_path.cep_adds_vect;
2095
2096 /* Set the common alternate address path fields */
2097 status = tavor_set_addr_path(state, adds_vect, qpc_path,
2098 TAVOR_ADDRPATH_QP, qp);
2099 if (status != DDI_SUCCESS) {
2100 TNF_PROBE_0(tavor_qp_rts2rts_setaddrpath_fail,
2101 TAVOR_TNF_ERROR, "");
2102 TAVOR_TNF_EXIT(tavor_qp_rts2rts);
2103 return (status);
2104 }
2105 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
2106
2107 /*
2108 * Check for valid alternate path port number and fill
2109 * it in
2110 */
2111 portnum = rc->rc_alt_path.cep_hca_port_num;
2112 if (tavor_portnum_is_valid(state, portnum)) {
2113 qpc->alt_addr_path.portnum = portnum;
2114 } else {
2115 TNF_PROBE_1(tavor_qp_rts2rts_inv_altport_fail,
2116 TAVOR_TNF_ERROR, "", tnf_uint, altport,
2117 portnum);
2118 TAVOR_TNF_EXIT(tavor_qp_rts2rts);
2119 return (IBT_HCA_PORT_INVALID);
2120 }
2121
2122 /*
2123 * Check for valid alternate path PKey index and fill
2124 * it in
2125 */
2126 pkeyindx = rc->rc_alt_path.cep_pkey_ix;
2127 if (tavor_pkeyindex_is_valid(state, pkeyindx)) {
2128 qpc->alt_addr_path.pkey_indx = pkeyindx;
2129 } else {
2130 TNF_PROBE_1(tavor_qp_rts2rts_inv_altpkey_fail,
2131 TAVOR_TNF_ERROR, "", tnf_uint, altpkeyindx,
2132 pkeyindx);
2133 TAVOR_TNF_EXIT(tavor_qp_rts2rts);
2134 return (IBT_PKEY_IX_ILLEGAL);
2135 }
2136 opmask |= TAVOR_CMD_OP_ALT_PATH;
2137 }
2138
2139 } else if (qp->qp_serv_type == TAVOR_QP_UC) {
2140 uc = &info_p->qp_transport.uc;
2141
2142 /*
2143 * Check if any of the flags indicate a change in the RDMA
2144 * Write (recv) enable/disable and set the appropriate flag
2145 * in the "opmask" parameter. Note: RDMA Read and Atomic are
2146 * not valid for UC transport.
2147 */
2148 if (flags & IBT_CEP_SET_RDMA_W) {
2149 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
2150 opmask |= TAVOR_CMD_OP_RWE;
2151 }
2152
2153 /*
2154 * If we are attempting to modify the path migration state for
2155 * this QP, then check for valid state and fill it in. Also
2156 * set the appropriate flag in the "opmask" parameter.
2157 */
2158 if (flags & IBT_CEP_SET_MIG) {
2159 if (uc->uc_mig_state == IBT_STATE_MIGRATED) {
2160 qpc->pm_state = TAVOR_QP_PMSTATE_MIGRATED;
2161 } else if (uc->uc_mig_state == IBT_STATE_REARMED) {
2162 qpc->pm_state = TAVOR_QP_PMSTATE_REARM;
2163 } else {
2164 TNF_PROBE_1(tavor_qp_rts2rts_inv_mig_state_fail,
2165 TAVOR_TNF_ERROR, "", tnf_uint, mig_state,
2166 uc->uc_mig_state);
2167 TAVOR_TNF_EXIT(tavor_qp_rts2rts);
2168 return (IBT_QP_APM_STATE_INVALID);
2169 }
2170 opmask |= TAVOR_CMD_OP_PM_STATE;
2171 }
2172
2173 /*
2174 * Check for optional alternate path and fill in the
2175 * appropriate QPC fields if one is specified
2176 */
2177 if (flags & IBT_CEP_SET_ALT_PATH) {
2178 qpc_path = &qpc->alt_addr_path;
2179 adds_vect = &uc->uc_alt_path.cep_adds_vect;
2180
2181 /* Set the common alternate address path fields */
2182 status = tavor_set_addr_path(state, adds_vect, qpc_path,
2183 TAVOR_ADDRPATH_QP, qp);
2184 if (status != DDI_SUCCESS) {
2185 TNF_PROBE_0(tavor_qp_rts2rts_setaddrpath_fail,
2186 TAVOR_TNF_ERROR, "");
2187 TAVOR_TNF_EXIT(tavor_qp_rts2rts);
2188 return (status);
2189 }
2190
2191 /*
2192 * Check for valid alternate path port number and fill
2193 * it in
2194 */
2195 portnum = uc->uc_alt_path.cep_hca_port_num;
2196 if (tavor_portnum_is_valid(state, portnum)) {
2197 qpc->alt_addr_path.portnum = portnum;
2198 } else {
2199 TNF_PROBE_1(tavor_qp_rts2rts_inv_altport_fail,
2200 TAVOR_TNF_ERROR, "", tnf_uint, altport,
2201 portnum);
2202 TAVOR_TNF_EXIT(tavor_qp_rts2rts);
2203 return (IBT_HCA_PORT_INVALID);
2204 }
2205
2206 /*
2207 * Check for valid alternate path PKey index and fill
2208 * it in
2209 */
2210 pkeyindx = uc->uc_alt_path.cep_pkey_ix;
2211 if (tavor_pkeyindex_is_valid(state, pkeyindx)) {
2212 qpc->alt_addr_path.pkey_indx = pkeyindx;
2213 } else {
2214 TNF_PROBE_1(tavor_qp_rts2rts_inv_altpkey_fail,
2215 TAVOR_TNF_ERROR, "", tnf_uint, altpkeyindx,
2216 pkeyindx);
2217 TAVOR_TNF_EXIT(tavor_qp_rts2rts);
2218 return (IBT_PKEY_IX_ILLEGAL);
2219 }
2220 opmask |= TAVOR_CMD_OP_ALT_PATH;
2221 }
2222 } else {
2223 /*
2224 * Invalid QP transport type. If we got here then it's a
2225 * warning of a probably serious problem. So print a message
2226 * and return failure
2227 */
2228 TAVOR_WARNING(state, "unknown QP transport type in rts2rts");
2229 TNF_PROBE_0(tavor_qp_rts2rts_inv_transtype_fail,
2230 TAVOR_TNF_ERROR, "");
2231 TAVOR_TNF_EXIT(tavor_qp_rts2rts);
2232 return (ibc_get_ci_failure(0));
2233 }
2234
2235 /*
2236 * Post the RTS2RTS_QP command to the Tavor firmware
2237 *
2238 * We do a TAVOR_NOSLEEP here because we are still holding the
2239 * "qp_lock". If we got raised to interrupt level by priority
2240 * inversion, we do not want to block in this routine waiting for
2241 * success.
2242 */
2243 status = tavor_cmn_qp_cmd_post(state, RTS2RTS_QP, qpc, qp->qp_qpnum,
2244 opmask, TAVOR_CMD_NOSLEEP_SPIN);
2245 if (status != TAVOR_CMD_SUCCESS) {
2246 if (status != TAVOR_CMD_BAD_QP_STATE) {
2247 cmn_err(CE_CONT, "Tavor: RTS2RTS_QP command failed: "
2248 "%08x\n", status);
2249 TNF_PROBE_1(tavor_qp_rts2rts_cmd_fail,
2250 TAVOR_TNF_ERROR, "", tnf_uint, status, status);
2251 TAVOR_TNF_EXIT(tavor_qp_rts2rts);
2252 return (ibc_get_ci_failure(0));
2253 } else {
2254 TNF_PROBE_0(tavor_qp_rts2rts_inv_qpstate_fail,
2255 TAVOR_TNF_ERROR, "");
2256 TAVOR_TNF_EXIT(tavor_qp_rts2rts);
2257 return (IBT_QP_STATE_INVALID);
2258 }
2259 }
2260
2261 TAVOR_TNF_EXIT(tavor_qp_rts2rts);
2262 return (DDI_SUCCESS);
2263 }
2264
2265
2266 /*
2267 * tavor_qp_rts2sqd()
2268 * Context: Can be called from interrupt or base context.
2269 */
2270 static int
tavor_qp_rts2sqd(tavor_state_t * state,tavor_qphdl_t qp,ibt_cep_modify_flags_t flags)2271 tavor_qp_rts2sqd(tavor_state_t *state, tavor_qphdl_t qp,
2272 ibt_cep_modify_flags_t flags)
2273 {
2274 int status;
2275
2276 TAVOR_TNF_ENTER(tavor_qp_rts2sqd);
2277
2278 ASSERT(MUTEX_HELD(&qp->qp_lock));
2279
2280 /*
2281 * Set a flag to indicate whether or not the consumer is interested
2282 * in receiving the SQ drained event. Since we are going to always
2283 * request hardware generation of the SQD event, we use the value in
2284 * "qp_forward_sqd_event" to determine whether or not to pass the event
2285 * to the IBTF or to silently consume it.
2286 */
2287 qp->qp_forward_sqd_event = (flags & IBT_CEP_SET_SQD_EVENT) ? 1 : 0;
2288
2289 /*
2290 * Post the RTS2SQD_QP command to the Tavor firmware
2291 *
2292 * We do a TAVOR_NOSLEEP here because we are still holding the
2293 * "qp_lock". If we got raised to interrupt level by priority
2294 * inversion, we do not want to block in this routine waiting for
2295 * success.
2296 */
2297 status = tavor_cmn_qp_cmd_post(state, RTS2SQD_QP, NULL, qp->qp_qpnum,
2298 0, TAVOR_CMD_NOSLEEP_SPIN);
2299 if (status != TAVOR_CMD_SUCCESS) {
2300 if (status != TAVOR_CMD_BAD_QP_STATE) {
2301 cmn_err(CE_CONT, "Tavor: RTS2SQD_QP command failed: "
2302 "%08x\n", status);
2303 TNF_PROBE_1(tavor_qp_rts2sqd_cmd_fail,
2304 TAVOR_TNF_ERROR, "", tnf_uint, status, status);
2305 TAVOR_TNF_EXIT(tavor_qp_rts2sqd);
2306 return (ibc_get_ci_failure(0));
2307 } else {
2308 TNF_PROBE_0(tavor_qp_rts2sqd_inv_qpstate_fail,
2309 TAVOR_TNF_ERROR, "");
2310 TAVOR_TNF_EXIT(tavor_qp_rts2sqd);
2311 return (IBT_QP_STATE_INVALID);
2312 }
2313 }
2314
2315 /*
2316 * Mark the current QP state as "SQ Draining". This allows us to
2317 * distinguish between the two underlying states in SQD. (see QueryQP()
2318 * code in tavor_qp.c)
2319 */
2320 qp->qp_sqd_still_draining = 1;
2321
2322 TAVOR_TNF_EXIT(tavor_qp_rts2sqd);
2323 return (DDI_SUCCESS);
2324 }
2325
2326
2327 /*
2328 * tavor_qp_sqd2rts()
2329 * Context: Can be called from interrupt or base context.
2330 */
2331 static int
tavor_qp_sqd2rts(tavor_state_t * state,tavor_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p)2332 tavor_qp_sqd2rts(tavor_state_t *state, tavor_qphdl_t qp,
2333 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p)
2334 {
2335 tavor_hw_qpc_t *qpc;
2336 ibt_qp_rc_attr_t *rc;
2337 ibt_qp_ud_attr_t *ud;
2338 ibt_qp_uc_attr_t *uc;
2339 tavor_hw_addr_path_t *qpc_path;
2340 ibt_adds_vect_t *adds_vect;
2341 uint_t portnum, pkeyindx;
2342 uint32_t opmask = 0;
2343 int status;
2344
2345 TAVOR_TNF_ENTER(tavor_qp_sqd2rts);
2346
2347 ASSERT(MUTEX_HELD(&qp->qp_lock));
2348
2349 /*
2350 * Grab the temporary QPC entry from QP software state
2351 */
2352 qpc = &qp->qpc;
2353
2354 /*
2355 * Since there are no common and/or Tavor-specific fields to be filled
2356 * in for this command, we begin with the QPC fields which are
2357 * specific to transport type.
2358 */
2359 if (qp->qp_serv_type == TAVOR_QP_UD) {
2360 ud = &info_p->qp_transport.ud;
2361
2362 /*
2363 * If we are attempting to modify the QKey for this QP, then
2364 * fill it in and set the appropriate flag in the "opmask"
2365 * parameter.
2366 */
2367 if (flags & IBT_CEP_SET_QKEY) {
2368 qpc->qkey = ud->ud_qkey;
2369 opmask |= TAVOR_CMD_OP_QKEY;
2370 }
2371
2372 } else if (qp->qp_serv_type == TAVOR_QP_RC) {
2373 rc = &info_p->qp_transport.rc;
2374
2375 /*
2376 * Check if any of the flags indicate a change in the RDMA
2377 * (recv) enable/disable flags and set the appropriate flag in
2378 * the "opmask" parameter
2379 */
2380 opmask |= tavor_check_rdma_enable_flags(flags, info_p, qpc);
2381
2382 /*
2383 * If we are attempting to modify the path migration state for
2384 * this QP, then check for valid state and fill it in. Also
2385 * set the appropriate flag in the "opmask" parameter.
2386 */
2387 if (flags & IBT_CEP_SET_MIG) {
2388 if (rc->rc_mig_state == IBT_STATE_MIGRATED) {
2389 qpc->pm_state = TAVOR_QP_PMSTATE_MIGRATED;
2390 } else if (rc->rc_mig_state == IBT_STATE_REARMED) {
2391 qpc->pm_state = TAVOR_QP_PMSTATE_REARM;
2392 } else {
2393 TNF_PROBE_1(tavor_qp_sqd2rts_inv_mig_state_fail,
2394 TAVOR_TNF_ERROR, "", tnf_uint, mig_state,
2395 rc->rc_mig_state);
2396 TAVOR_TNF_EXIT(tavor_qp_sqd2rts);
2397 return (IBT_QP_APM_STATE_INVALID);
2398 }
2399 opmask |= TAVOR_CMD_OP_PM_STATE;
2400 }
2401
2402 /*
2403 * Check for optional alternate path and fill in the
2404 * appropriate QPC fields if one is specified
2405 */
2406 if (flags & IBT_CEP_SET_ALT_PATH) {
2407 qpc_path = &qpc->alt_addr_path;
2408 adds_vect = &rc->rc_alt_path.cep_adds_vect;
2409
2410 /* Set the common alternate address path fields */
2411 status = tavor_set_addr_path(state, adds_vect, qpc_path,
2412 TAVOR_ADDRPATH_QP, qp);
2413 if (status != DDI_SUCCESS) {
2414 TNF_PROBE_0(tavor_qp_sqd2rts_setaddrpath_fail,
2415 TAVOR_TNF_ERROR, "");
2416 TAVOR_TNF_EXIT(tavor_qp_sqd2rts);
2417 return (status);
2418 }
2419 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
2420
2421 /*
2422 * Check for valid alternate path port number and fill
2423 * it in
2424 */
2425 portnum = rc->rc_alt_path.cep_hca_port_num;
2426 if (tavor_portnum_is_valid(state, portnum)) {
2427 qpc->alt_addr_path.portnum = portnum;
2428 } else {
2429 TNF_PROBE_1(tavor_qp_sqd2rts_inv_altport_fail,
2430 TAVOR_TNF_ERROR, "", tnf_uint, altport,
2431 portnum);
2432 TAVOR_TNF_EXIT(tavor_qp_sqd2rts);
2433 return (IBT_HCA_PORT_INVALID);
2434 }
2435
2436 /*
2437 * Check for valid alternate path PKey index and fill
2438 * it in
2439 */
2440 pkeyindx = rc->rc_alt_path.cep_pkey_ix;
2441 if (tavor_pkeyindex_is_valid(state, pkeyindx)) {
2442 qpc->alt_addr_path.pkey_indx = pkeyindx;
2443 } else {
2444 TNF_PROBE_1(tavor_qp_sqd2rts_inv_altpkey_fail,
2445 TAVOR_TNF_ERROR, "", tnf_uint, altpkeyindx,
2446 pkeyindx);
2447 TAVOR_TNF_EXIT(tavor_qp_sqd2rts);
2448 return (IBT_PKEY_IX_ILLEGAL);
2449 }
2450 opmask |= TAVOR_CMD_OP_ALT_PATH;
2451 }
2452
2453 /*
2454 * If we are attempting to modify the "Minimum RNR NAK" value
2455 * for this QP, then fill it in and set the appropriate flag
2456 * in the "opmask" parameter.
2457 */
2458 if (flags & IBT_CEP_SET_MIN_RNR_NAK) {
2459 qpc->min_rnr_nak = rc->rc_min_rnr_nak;
2460 opmask |= TAVOR_CMD_OP_MINRNRNAK;
2461 }
2462
2463 } else if (qp->qp_serv_type == TAVOR_QP_UC) {
2464 uc = &info_p->qp_transport.uc;
2465
2466 /*
2467 * Check if any of the flags indicate a change in the RDMA
2468 * Write (recv) enable/disable and set the appropriate flag
2469 * in the "opmask" parameter. Note: RDMA Read and Atomic are
2470 * not valid for UC transport.
2471 */
2472 if (flags & IBT_CEP_SET_RDMA_W) {
2473 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
2474 opmask |= TAVOR_CMD_OP_RWE;
2475 }
2476
2477 /*
2478 * If we are attempting to modify the path migration state for
2479 * this QP, then check for valid state and fill it in. Also
2480 * set the appropriate flag in the "opmask" parameter.
2481 */
2482 if (flags & IBT_CEP_SET_MIG) {
2483 if (uc->uc_mig_state == IBT_STATE_MIGRATED) {
2484 qpc->pm_state = TAVOR_QP_PMSTATE_MIGRATED;
2485 } else if (uc->uc_mig_state == IBT_STATE_REARMED) {
2486 qpc->pm_state = TAVOR_QP_PMSTATE_REARM;
2487 } else {
2488 TNF_PROBE_1(tavor_qp_sqd2rts_inv_mig_state_fail,
2489 TAVOR_TNF_ERROR, "", tnf_uint, mig_state,
2490 uc->uc_mig_state);
2491 TAVOR_TNF_EXIT(tavor_qp_sqd2rts);
2492 return (IBT_QP_APM_STATE_INVALID);
2493 }
2494 opmask |= TAVOR_CMD_OP_PM_STATE;
2495 }
2496
2497 /*
2498 * Check for optional alternate path and fill in the
2499 * appropriate QPC fields if one is specified
2500 */
2501 if (flags & IBT_CEP_SET_ALT_PATH) {
2502 qpc_path = &qpc->alt_addr_path;
2503 adds_vect = &uc->uc_alt_path.cep_adds_vect;
2504
2505 /* Set the common alternate address path fields */
2506 status = tavor_set_addr_path(state, adds_vect, qpc_path,
2507 TAVOR_ADDRPATH_QP, qp);
2508 if (status != DDI_SUCCESS) {
2509 TNF_PROBE_0(tavor_qp_sqd2rts_setaddrpath_fail,
2510 TAVOR_TNF_ERROR, "");
2511 TAVOR_TNF_EXIT(tavor_qp_sqd2rts);
2512 return (status);
2513 }
2514
2515 /*
2516 * Check for valid alternate path port number and fill
2517 * it in
2518 */
2519 portnum = uc->uc_alt_path.cep_hca_port_num;
2520 if (tavor_portnum_is_valid(state, portnum)) {
2521 qpc->alt_addr_path.portnum = portnum;
2522 } else {
2523 TNF_PROBE_1(tavor_qp_sqd2rts_inv_altport_fail,
2524 TAVOR_TNF_ERROR, "", tnf_uint, altport,
2525 portnum);
2526 TAVOR_TNF_EXIT(tavor_qp_sqd2rts);
2527 return (IBT_HCA_PORT_INVALID);
2528 }
2529
2530 /*
2531 * Check for valid alternate path PKey index and fill
2532 * it in
2533 */
2534 pkeyindx = uc->uc_alt_path.cep_pkey_ix;
2535 if (tavor_pkeyindex_is_valid(state, pkeyindx)) {
2536 qpc->alt_addr_path.pkey_indx = pkeyindx;
2537 } else {
2538 TNF_PROBE_1(tavor_qp_sqd2rts_inv_altpkey_fail,
2539 TAVOR_TNF_ERROR, "", tnf_uint, altpkeyindx,
2540 pkeyindx);
2541 TAVOR_TNF_EXIT(tavor_qp_sqd2rts);
2542 return (IBT_PKEY_IX_ILLEGAL);
2543 }
2544 opmask |= TAVOR_CMD_OP_ALT_PATH;
2545 }
2546 } else {
2547 /*
2548 * Invalid QP transport type. If we got here then it's a
2549 * warning of a probably serious problem. So print a message
2550 * and return failure
2551 */
2552 TAVOR_WARNING(state, "unknown QP transport type in sqd2rts");
2553 TNF_PROBE_0(tavor_qp_sqd2rts_inv_transtype_fail,
2554 TAVOR_TNF_ERROR, "");
2555 TAVOR_TNF_EXIT(tavor_qp_sqd2rts);
2556 return (ibc_get_ci_failure(0));
2557 }
2558
2559 /*
2560 * Post the SQD2RTS_QP command to the Tavor firmware
2561 *
2562 * We do a TAVOR_NOSLEEP here because we are still holding the
2563 * "qp_lock". If we got raised to interrupt level by priority
2564 * inversion, we do not want to block in this routine waiting for
2565 * success.
2566 */
2567 status = tavor_cmn_qp_cmd_post(state, SQD2RTS_QP, qpc, qp->qp_qpnum,
2568 opmask, TAVOR_CMD_NOSLEEP_SPIN);
2569 if (status != TAVOR_CMD_SUCCESS) {
2570 if (status != TAVOR_CMD_BAD_QP_STATE) {
2571 cmn_err(CE_CONT, "Tavor: SQD2RTS_QP command failed: "
2572 "%08x\n", status);
2573 TNF_PROBE_1(tavor_qp_sqd2rts_cmd_fail,
2574 TAVOR_TNF_ERROR, "", tnf_uint, status, status);
2575 TAVOR_TNF_EXIT(tavor_qp_sqd2rts);
2576 return (ibc_get_ci_failure(0));
2577 } else {
2578 TNF_PROBE_0(tavor_qp_sqd2rts_inv_qpstate_fail,
2579 TAVOR_TNF_ERROR, "");
2580 TAVOR_TNF_EXIT(tavor_qp_sqd2rts);
2581 return (IBT_QP_STATE_INVALID);
2582 }
2583 }
2584
2585 TAVOR_TNF_EXIT(tavor_qp_sqd2rts);
2586 return (DDI_SUCCESS);
2587 }
2588
2589
2590 /*
2591 * tavor_qp_sqd2sqd()
2592 * Context: Can be called from interrupt or base context.
2593 */
2594 static int
tavor_qp_sqd2sqd(tavor_state_t * state,tavor_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p)2595 tavor_qp_sqd2sqd(tavor_state_t *state, tavor_qphdl_t qp,
2596 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p)
2597 {
2598 tavor_hw_qpc_t *qpc;
2599 ibt_qp_rc_attr_t *rc;
2600 ibt_qp_ud_attr_t *ud;
2601 ibt_qp_uc_attr_t *uc;
2602 tavor_hw_addr_path_t *qpc_path;
2603 ibt_adds_vect_t *adds_vect;
2604 uint_t portnum, pkeyindx, rdma_ra_out, rdma_ra_in;
2605 uint_t rra_max, sra_max;
2606 uint32_t opmask = 0;
2607 int status;
2608
2609 TAVOR_TNF_ENTER(tavor_qp_sqd2sqd);
2610
2611 ASSERT(MUTEX_HELD(&qp->qp_lock));
2612
2613 /*
2614 * Grab the temporary QPC entry from QP software state
2615 */
2616 qpc = &qp->qpc;
2617
2618 /*
2619 * Since there are no common and/or Tavor-specific fields to be filled
2620 * in for this command, we begin with the QPC fields which are
2621 * specific to transport type.
2622 */
2623 if (qp->qp_serv_type == TAVOR_QP_UD) {
2624 ud = &info_p->qp_transport.ud;
2625
2626 /*
2627 * If we are attempting to modify the PKey index for this QP,
2628 * then check for valid PKey index and fill it in. Also set
2629 * the appropriate flag in the "opmask" parameter.
2630 */
2631 if (flags & IBT_CEP_SET_PKEY_IX) {
2632 pkeyindx = ud->ud_pkey_ix;
2633 if (tavor_pkeyindex_is_valid(state, pkeyindx)) {
2634 qpc->pri_addr_path.pkey_indx = pkeyindx;
2635 opmask |= TAVOR_CMD_OP_PKEYINDX;
2636 qp->qp_pkeyindx = pkeyindx;
2637 } else {
2638 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_pkey_fail,
2639 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx,
2640 pkeyindx);
2641 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd);
2642 return (IBT_PKEY_IX_ILLEGAL);
2643 }
2644 }
2645
2646 /*
2647 * If we are attempting to modify the QKey for this QP, then
2648 * fill it in and set the appropriate flag in the "opmask"
2649 * parameter.
2650 */
2651 if (flags & IBT_CEP_SET_QKEY) {
2652 qpc->qkey = ud->ud_qkey;
2653 opmask |= TAVOR_CMD_OP_QKEY;
2654 }
2655
2656 } else if (qp->qp_serv_type == TAVOR_QP_RC) {
2657 rc = &info_p->qp_transport.rc;
2658
2659 /*
2660 * Check if any of the flags indicate a change in the RDMA
2661 * (recv) enable/disable flags and set the appropriate flag in
2662 * the "opmask" parameter
2663 */
2664 opmask |= tavor_check_rdma_enable_flags(flags, info_p, qpc);
2665
2666 /*
2667 * Check for optional primary path and fill in the
2668 * appropriate QPC fields if one is specified
2669 */
2670 if (flags & IBT_CEP_SET_ADDS_VECT) {
2671 qpc_path = &qpc->pri_addr_path;
2672 adds_vect = &rc->rc_path.cep_adds_vect;
2673
2674 /* Set the common primary address path fields */
2675 status = tavor_set_addr_path(state, adds_vect, qpc_path,
2676 TAVOR_ADDRPATH_QP, qp);
2677 if (status != DDI_SUCCESS) {
2678 TNF_PROBE_0(tavor_qp_sqd2sqd_setaddrpath_fail,
2679 TAVOR_TNF_ERROR, "");
2680 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd);
2681 return (status);
2682 }
2683 qpc_path->rnr_retry = rc->rc_rnr_retry_cnt;
2684 qpc_path->ack_timeout = rc->rc_path.cep_timeout;
2685 qpc->retry_cnt = rc->rc_retry_cnt;
2686
2687 /*
2688 * MTU changes as part of sqd2sqd are not allowed.
2689 * Simply keep the same MTU value here, stored in the
2690 * qphdl from init2rtr time.
2691 */
2692 qpc->mtu = qp->qp_save_mtu;
2693
2694 opmask |= (TAVOR_CMD_OP_PRIM_PATH |
2695 TAVOR_CMD_OP_RETRYCNT | TAVOR_CMD_OP_ACKTIMEOUT |
2696 TAVOR_CMD_OP_PRIM_RNRRETRY);
2697 }
2698
2699 /*
2700 * If we are attempting to modify the path migration state for
2701 * this QP, then check for valid state and fill it in. Also
2702 * set the appropriate flag in the "opmask" parameter.
2703 */
2704 if (flags & IBT_CEP_SET_MIG) {
2705 if (rc->rc_mig_state == IBT_STATE_MIGRATED) {
2706 qpc->pm_state = TAVOR_QP_PMSTATE_MIGRATED;
2707 } else if (rc->rc_mig_state == IBT_STATE_REARMED) {
2708 qpc->pm_state = TAVOR_QP_PMSTATE_REARM;
2709 } else {
2710 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_mig_state_fail,
2711 TAVOR_TNF_ERROR, "", tnf_uint, mig_state,
2712 rc->rc_mig_state);
2713 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd);
2714 return (IBT_QP_APM_STATE_INVALID);
2715 }
2716 opmask |= TAVOR_CMD_OP_PM_STATE;
2717 }
2718
2719 /*
2720 * If we are attempting to modify the PKey index for this QP,
2721 * then check for valid PKey index and fill it in. Also set
2722 * the appropriate flag in the "opmask" parameter.
2723 */
2724 if (flags & IBT_CEP_SET_PKEY_IX) {
2725 pkeyindx = rc->rc_path.cep_pkey_ix;
2726 if (tavor_pkeyindex_is_valid(state, pkeyindx)) {
2727 qpc->pri_addr_path.pkey_indx = pkeyindx;
2728 opmask |= TAVOR_CMD_OP_PKEYINDX;
2729 } else {
2730 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_pkey_fail,
2731 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx,
2732 pkeyindx);
2733 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd);
2734 return (IBT_PKEY_IX_ILLEGAL);
2735 }
2736 }
2737
2738 /*
2739 * If we are attempting to modify the port for this QP, then
2740 * check for valid port number and fill it in. Also set the
2741 * appropriate flag in the "opmask" parameter.
2742 */
2743 if (flags & IBT_CEP_SET_PORT) {
2744 portnum = rc->rc_path.cep_hca_port_num;
2745 if (tavor_portnum_is_valid(state, portnum)) {
2746 qpc->pri_addr_path.portnum = portnum;
2747 } else {
2748 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_port_fail,
2749 TAVOR_TNF_ERROR, "", tnf_uint, port,
2750 portnum);
2751 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd);
2752 return (IBT_HCA_PORT_INVALID);
2753 }
2754 opmask |= TAVOR_CMD_OP_PRIM_PORT;
2755 }
2756
2757 /*
2758 * Check for optional alternate path and fill in the
2759 * appropriate QPC fields if one is specified
2760 */
2761 if (flags & IBT_CEP_SET_ALT_PATH) {
2762 qpc_path = &qpc->alt_addr_path;
2763 adds_vect = &rc->rc_alt_path.cep_adds_vect;
2764
2765 /* Set the common alternate address path fields */
2766 status = tavor_set_addr_path(state, adds_vect, qpc_path,
2767 TAVOR_ADDRPATH_QP, qp);
2768 if (status != DDI_SUCCESS) {
2769 TNF_PROBE_0(tavor_qp_sqd2sqd_setaddrpath_fail,
2770 TAVOR_TNF_ERROR, "");
2771 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd);
2772 return (status);
2773 }
2774 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
2775
2776 /*
2777 * Check for valid alternate path port number and fill
2778 * it in
2779 */
2780 portnum = rc->rc_alt_path.cep_hca_port_num;
2781 if (tavor_portnum_is_valid(state, portnum)) {
2782 qpc->alt_addr_path.portnum = portnum;
2783 } else {
2784 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_altport_fail,
2785 TAVOR_TNF_ERROR, "", tnf_uint, altport,
2786 portnum);
2787 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd);
2788 return (IBT_HCA_PORT_INVALID);
2789 }
2790
2791 /*
2792 * Check for valid alternate path PKey index and fill
2793 * it in
2794 */
2795 pkeyindx = rc->rc_alt_path.cep_pkey_ix;
2796 if (tavor_pkeyindex_is_valid(state, pkeyindx)) {
2797 qpc->alt_addr_path.pkey_indx = pkeyindx;
2798 } else {
2799 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_altpkey_fail,
2800 TAVOR_TNF_ERROR, "", tnf_uint, altpkeyindx,
2801 pkeyindx);
2802 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd);
2803 return (IBT_PKEY_IX_ILLEGAL);
2804 }
2805 opmask |= TAVOR_CMD_OP_ALT_PATH;
2806 }
2807
2808 /*
2809 * If we are attempting to modify the number of "outgoing
2810 * RDMA resources" for this QP, then check for valid value and
2811 * fill it in. Also set the appropriate flag in the "opmask"
2812 * parameter.
2813 */
2814 if (flags & IBT_CEP_SET_RDMARA_OUT) {
2815 rdma_ra_out = rc->rc_rdma_ra_out;
2816 if (tavor_qp_validate_init_depth(state, rc,
2817 &sra_max) != DDI_SUCCESS) {
2818 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_rdma_out_fail,
2819 TAVOR_TNF_ERROR, "", tnf_uint, rdma_ra_out,
2820 rdma_ra_out);
2821 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd);
2822 return (IBT_INVALID_PARAM);
2823 }
2824 qpc->sra_max = sra_max;
2825 opmask |= TAVOR_CMD_OP_SRA_SET;
2826 }
2827
2828 /*
2829 * If we are attempting to modify the number of "incoming
2830 * RDMA resources" for this QP, then check for valid value and
2831 * update the "rra_max" and "ra_buf_index" fields in the QPC to
2832 * point to the pre-allocated RDB resources (in DDR). Also set
2833 * the appropriate flag in the "opmask" parameter.
2834 */
2835 if (flags & IBT_CEP_SET_RDMARA_IN) {
2836 rdma_ra_in = rc->rc_rdma_ra_in;
2837 if (tavor_qp_validate_resp_rsrc(state, rc,
2838 &rra_max) != DDI_SUCCESS) {
2839 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_rdma_in_fail,
2840 TAVOR_TNF_ERROR, "", tnf_uint, rdma_ra_in,
2841 rdma_ra_in);
2842 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd);
2843 return (IBT_INVALID_PARAM);
2844 }
2845 qpc->rra_max = rra_max;
2846 qpc->ra_buff_indx = qp->qp_rdb_ddraddr >>
2847 TAVOR_RDB_SIZE_SHIFT;
2848 opmask |= TAVOR_CMD_OP_RRA_SET;
2849 }
2850
2851 /*
2852 * If we are attempting to modify the "Local Ack Timeout" value
2853 * for this QP, then fill it in and set the appropriate flag in
2854 * the "opmask" parameter.
2855 */
2856 if (flags & IBT_CEP_SET_TIMEOUT) {
2857 qpc_path = &qpc->pri_addr_path;
2858 qpc_path->ack_timeout = rc->rc_path.cep_timeout;
2859 opmask |= TAVOR_CMD_OP_ACKTIMEOUT;
2860 }
2861
2862 /*
2863 * If we are attempting to modify the "Retry Count" for this QP,
2864 * then fill it in and set the appropriate flag in the "opmask"
2865 * parameter.
2866 */
2867 if (flags & IBT_CEP_SET_RETRY) {
2868 qpc->retry_cnt = rc->rc_retry_cnt;
2869 opmask |= TAVOR_CMD_OP_PRIM_RNRRETRY;
2870 }
2871
2872 /*
2873 * If we are attempting to modify the "RNR Retry Count" for this
2874 * QP, then fill it in and set the appropriate flag in the
2875 * "opmask" parameter.
2876 */
2877 if (flags & IBT_CEP_SET_RNR_NAK_RETRY) {
2878 qpc_path = &qpc->pri_addr_path;
2879 qpc_path->rnr_retry = rc->rc_rnr_retry_cnt;
2880 opmask |= TAVOR_CMD_OP_RETRYCNT;
2881 }
2882
2883 /*
2884 * If we are attempting to modify the "Minimum RNR NAK" value
2885 * for this QP, then fill it in and set the appropriate flag
2886 * in the "opmask" parameter.
2887 */
2888 if (flags & IBT_CEP_SET_MIN_RNR_NAK) {
2889 qpc->min_rnr_nak = rc->rc_min_rnr_nak;
2890 opmask |= TAVOR_CMD_OP_MINRNRNAK;
2891 }
2892
2893 } else if (qp->qp_serv_type == TAVOR_QP_UC) {
2894 uc = &info_p->qp_transport.uc;
2895
2896 /*
2897 * Check if any of the flags indicate a change in the RDMA
2898 * Write (recv) enable/disable and set the appropriate flag
2899 * in the "opmask" parameter. Note: RDMA Read and Atomic are
2900 * not valid for UC transport.
2901 */
2902 if (flags & IBT_CEP_SET_RDMA_W) {
2903 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
2904 opmask |= TAVOR_CMD_OP_RWE;
2905 }
2906
2907 /*
2908 * Check for optional primary path and fill in the
2909 * appropriate QPC fields if one is specified
2910 */
2911 if (flags & IBT_CEP_SET_ADDS_VECT) {
2912 qpc_path = &qpc->pri_addr_path;
2913 adds_vect = &uc->uc_path.cep_adds_vect;
2914
2915 /* Set the common primary address path fields */
2916 status = tavor_set_addr_path(state, adds_vect, qpc_path,
2917 TAVOR_ADDRPATH_QP, qp);
2918 if (status != DDI_SUCCESS) {
2919 TNF_PROBE_0(tavor_qp_sqd2sqd_setaddrpath_fail,
2920 TAVOR_TNF_ERROR, "");
2921 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd);
2922 return (status);
2923 }
2924
2925 /*
2926 * MTU changes as part of sqd2sqd are not allowed.
2927 * Simply keep the same MTU value here, stored in the
2928 * qphdl from init2rtr time.
2929 */
2930 qpc->mtu = qp->qp_save_mtu;
2931
2932 opmask |= TAVOR_CMD_OP_PRIM_PATH;
2933 }
2934
2935 /*
2936 * If we are attempting to modify the path migration state for
2937 * this QP, then check for valid state and fill it in. Also
2938 * set the appropriate flag in the "opmask" parameter.
2939 */
2940 if (flags & IBT_CEP_SET_MIG) {
2941 if (uc->uc_mig_state == IBT_STATE_MIGRATED) {
2942 qpc->pm_state = TAVOR_QP_PMSTATE_MIGRATED;
2943 } else if (uc->uc_mig_state == IBT_STATE_REARMED) {
2944 qpc->pm_state = TAVOR_QP_PMSTATE_REARM;
2945 } else {
2946 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_mig_state_fail,
2947 TAVOR_TNF_ERROR, "", tnf_uint, mig_state,
2948 uc->uc_mig_state);
2949 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd);
2950 return (IBT_QP_APM_STATE_INVALID);
2951 }
2952 opmask |= TAVOR_CMD_OP_PM_STATE;
2953 }
2954
2955 /*
2956 * If we are attempting to modify the PKey index for this QP,
2957 * then check for valid PKey index and fill it in. Also set
2958 * the appropriate flag in the "opmask" parameter.
2959 */
2960 if (flags & IBT_CEP_SET_PKEY_IX) {
2961 pkeyindx = uc->uc_path.cep_pkey_ix;
2962 if (tavor_pkeyindex_is_valid(state, pkeyindx)) {
2963 qpc->pri_addr_path.pkey_indx = pkeyindx;
2964 opmask |= TAVOR_CMD_OP_PKEYINDX;
2965 } else {
2966 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_pkey,
2967 TAVOR_TNF_ERROR, "", tnf_uint, pkeyindx,
2968 pkeyindx);
2969 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd);
2970 return (IBT_PKEY_IX_ILLEGAL);
2971 }
2972 }
2973
2974 /*
2975 * Check for optional alternate path and fill in the
2976 * appropriate QPC fields if one is specified
2977 */
2978 if (flags & IBT_CEP_SET_ALT_PATH) {
2979 qpc_path = &qpc->alt_addr_path;
2980 adds_vect = &uc->uc_alt_path.cep_adds_vect;
2981
2982 /* Set the common alternate address path fields */
2983 status = tavor_set_addr_path(state, adds_vect, qpc_path,
2984 TAVOR_ADDRPATH_QP, qp);
2985 if (status != DDI_SUCCESS) {
2986 TNF_PROBE_0(tavor_qp_sqd2sqd_setaddrpath_fail,
2987 TAVOR_TNF_ERROR, "");
2988 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd);
2989 return (status);
2990 }
2991
2992 /*
2993 * Check for valid alternate path port number and fill
2994 * it in
2995 */
2996 portnum = uc->uc_alt_path.cep_hca_port_num;
2997 if (tavor_portnum_is_valid(state, portnum)) {
2998 qpc->alt_addr_path.portnum = portnum;
2999 } else {
3000 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_altport_fail,
3001 TAVOR_TNF_ERROR, "", tnf_uint, altport,
3002 portnum);
3003 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd);
3004 return (IBT_HCA_PORT_INVALID);
3005 }
3006
3007 /*
3008 * Check for valid alternate path PKey index and fill
3009 * it in
3010 */
3011 pkeyindx = uc->uc_alt_path.cep_pkey_ix;
3012 if (tavor_pkeyindex_is_valid(state, pkeyindx)) {
3013 qpc->alt_addr_path.pkey_indx = pkeyindx;
3014 } else {
3015 TNF_PROBE_1(tavor_qp_sqd2sqd_inv_altpkey_fail,
3016 TAVOR_TNF_ERROR, "", tnf_uint, altpkeyindx,
3017 pkeyindx);
3018 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd);
3019 return (IBT_PKEY_IX_ILLEGAL);
3020 }
3021 opmask |= TAVOR_CMD_OP_ALT_PATH;
3022 }
3023 } else {
3024 /*
3025 * Invalid QP transport type. If we got here then it's a
3026 * warning of a probably serious problem. So print a message
3027 * and return failure
3028 */
3029 TAVOR_WARNING(state, "unknown QP transport type in sqd2sqd");
3030 TNF_PROBE_0(tavor_qp_sqd2sqd_inv_transtype_fail,
3031 TAVOR_TNF_ERROR, "");
3032 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd);
3033 return (ibc_get_ci_failure(0));
3034 }
3035
3036 /*
3037 * Post the SQD2SQD_QP command to the Tavor firmware
3038 *
3039 * We do a TAVOR_NOSLEEP here because we are still holding the
3040 * "qp_lock". If we got raised to interrupt level by priority
3041 * inversion, we do not want to block in this routine waiting for
3042 * success.
3043 */
3044 status = tavor_cmn_qp_cmd_post(state, SQD2SQD_QP, qpc, qp->qp_qpnum,
3045 opmask, TAVOR_CMD_NOSLEEP_SPIN);
3046 if (status != TAVOR_CMD_SUCCESS) {
3047 if (status != TAVOR_CMD_BAD_QP_STATE) {
3048 cmn_err(CE_CONT, "Tavor: SQD2SQD_QP command failed: "
3049 "%08x\n", status);
3050 TNF_PROBE_1(tavor_qp_sqd2sqd_cmd_fail,
3051 TAVOR_TNF_ERROR, "", tnf_uint, status, status);
3052 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd);
3053 return (ibc_get_ci_failure(0));
3054 } else {
3055 TNF_PROBE_0(tavor_qp_sqd2sqd_inv_qpstate_fail,
3056 TAVOR_TNF_ERROR, "");
3057 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd);
3058 return (IBT_QP_STATE_INVALID);
3059 }
3060 }
3061
3062 TAVOR_TNF_EXIT(tavor_qp_sqd2sqd);
3063 return (DDI_SUCCESS);
3064 }
3065
3066
3067 /*
3068 * tavor_qp_sqerr2rts()
3069 * Context: Can be called from interrupt or base context.
3070 */
3071 static int
tavor_qp_sqerr2rts(tavor_state_t * state,tavor_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p)3072 tavor_qp_sqerr2rts(tavor_state_t *state, tavor_qphdl_t qp,
3073 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p)
3074 {
3075 tavor_hw_qpc_t *qpc;
3076 ibt_qp_ud_attr_t *ud;
3077 uint32_t opmask = 0;
3078 int status;
3079
3080 TAVOR_TNF_ENTER(tavor_qp_sqerr2rts);
3081
3082 ASSERT(MUTEX_HELD(&qp->qp_lock));
3083
3084 /*
3085 * Grab the temporary QPC entry from QP software state
3086 */
3087 qpc = &qp->qpc;
3088
3089 /*
3090 * Since there are no common and/or Tavor-specific fields to be filled
3091 * in for this command, we begin with the QPC fields which are
3092 * specific to transport type.
3093 */
3094 if (qp->qp_serv_type == TAVOR_QP_UD) {
3095 ud = &info_p->qp_transport.ud;
3096
3097 /*
3098 * If we are attempting to modify the QKey for this QP, then
3099 * fill it in and set the appropriate flag in the "opmask"
3100 * parameter.
3101 */
3102 if (flags & IBT_CEP_SET_QKEY) {
3103 qpc->qkey = ud->ud_qkey;
3104 opmask |= TAVOR_CMD_OP_QKEY;
3105 }
3106
3107 } else if (qp->qp_serv_type == TAVOR_QP_UC) {
3108
3109 /*
3110 * Check if any of the flags indicate a change in the RDMA
3111 * Write (recv) enable/disable and set the appropriate flag
3112 * in the "opmask" parameter. Note: RDMA Read and Atomic are
3113 * not valid for UC transport.
3114 */
3115 if (flags & IBT_CEP_SET_RDMA_W) {
3116 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
3117 opmask |= TAVOR_CMD_OP_RWE;
3118 }
3119 } else {
3120 /*
3121 * Invalid QP transport type. If we got here then it's a
3122 * warning of a probably serious problem. So print a message
3123 * and return failure
3124 */
3125 TAVOR_WARNING(state, "unknown QP transport type in sqerr2rts");
3126 TNF_PROBE_0(tavor_qp_sqerr2rts_inv_transtype_fail,
3127 TAVOR_TNF_ERROR, "");
3128 TAVOR_TNF_EXIT(tavor_qp_sqerr2rts);
3129 return (ibc_get_ci_failure(0));
3130 }
3131
3132 /*
3133 * Post the SQERR2RTS_QP command to the Tavor firmware
3134 *
3135 * We do a TAVOR_NOSLEEP here because we are still holding the
3136 * "qp_lock". If we got raised to interrupt level by priority
3137 * inversion, we do not want to block in this routine waiting for
3138 * success.
3139 */
3140 status = tavor_cmn_qp_cmd_post(state, SQERR2RTS_QP, qpc, qp->qp_qpnum,
3141 opmask, TAVOR_CMD_NOSLEEP_SPIN);
3142 if (status != TAVOR_CMD_SUCCESS) {
3143 if (status != TAVOR_CMD_BAD_QP_STATE) {
3144 cmn_err(CE_CONT, "Tavor: SQERR2RTS_QP command failed: "
3145 "%08x\n", status);
3146 TNF_PROBE_1(tavor_qp_sqerr2rts_cmd_fail,
3147 TAVOR_TNF_ERROR, "", tnf_uint, status, status);
3148 TAVOR_TNF_EXIT(tavor_qp_sqerr2rts);
3149 return (ibc_get_ci_failure(0));
3150 } else {
3151 TNF_PROBE_0(tavor_qp_sqerr2rts_inv_qpstate_fail,
3152 TAVOR_TNF_ERROR, "");
3153 TAVOR_TNF_EXIT(tavor_qp_sqerr2rts);
3154 return (IBT_QP_STATE_INVALID);
3155 }
3156 }
3157
3158 TAVOR_TNF_EXIT(tavor_qp_sqerr2rts);
3159 return (DDI_SUCCESS);
3160 }
3161
3162
3163 /*
3164 * tavor_qp_to_error()
3165 * Context: Can be called from interrupt or base context.
3166 */
3167 static int
tavor_qp_to_error(tavor_state_t * state,tavor_qphdl_t qp)3168 tavor_qp_to_error(tavor_state_t *state, tavor_qphdl_t qp)
3169 {
3170 int status;
3171
3172 TAVOR_TNF_ENTER(tavor_qp_to_error);
3173
3174 ASSERT(MUTEX_HELD(&qp->qp_lock));
3175
3176 /*
3177 * Post the TOERR_QP command to the Tavor firmware
3178 *
3179 * We do a TAVOR_NOSLEEP here because we are still holding the
3180 * "qp_lock". If we got raised to interrupt level by priority
3181 * inversion, we do not want to block in this routine waiting for
3182 * success.
3183 */
3184 status = tavor_cmn_qp_cmd_post(state, TOERR_QP, NULL, qp->qp_qpnum,
3185 0, TAVOR_CMD_NOSLEEP_SPIN);
3186 if (status != TAVOR_CMD_SUCCESS) {
3187 cmn_err(CE_CONT, "Tavor: TOERR_QP command failed: %08x\n",
3188 status);
3189 TNF_PROBE_1(tavor_qp_to_error_cmd_fail,
3190 TAVOR_TNF_ERROR, "", tnf_uint, status, status);
3191 TAVOR_TNF_EXIT(tavor_qp_to_error);
3192 return (ibc_get_ci_failure(0));
3193 }
3194
3195 TAVOR_TNF_EXIT(tavor_qp_to_error);
3196 return (DDI_SUCCESS);
3197 }
3198
3199
3200 /*
3201 * tavor_qp_to_reset()
3202 * Context: Can be called from interrupt or base context.
3203 */
3204 int
tavor_qp_to_reset(tavor_state_t * state,tavor_qphdl_t qp)3205 tavor_qp_to_reset(tavor_state_t *state, tavor_qphdl_t qp)
3206 {
3207 tavor_hw_qpc_t *qpc;
3208 int status;
3209
3210 TAVOR_TNF_ENTER(tavor_qp_to_reset);
3211
3212 ASSERT(MUTEX_HELD(&qp->qp_lock));
3213
3214 /*
3215 * Grab the temporary QPC entry from QP software state
3216 */
3217 qpc = &qp->qpc;
3218
3219 /*
3220 * Post the TORST_QP command to the Tavor firmware
3221 *
3222 * We do a TAVOR_NOSLEEP here because we are still holding the
3223 * "qp_lock". If we got raised to interrupt level by priority
3224 * inversion, we do not want to block in this routine waiting for
3225 * success.
3226 */
3227 status = tavor_cmn_qp_cmd_post(state, TORST_QP, qpc, qp->qp_qpnum,
3228 0, TAVOR_CMD_NOSLEEP_SPIN);
3229 if (status != TAVOR_CMD_SUCCESS) {
3230 cmn_err(CE_CONT, "Tavor: TORST_QP command failed: %08x\n",
3231 status);
3232 TNF_PROBE_1(tavor_qp_to_reset_cmd_fail,
3233 TAVOR_TNF_ERROR, "", tnf_uint, status, status);
3234 TAVOR_TNF_EXIT(tavor_qp_to_reset);
3235 return (ibc_get_ci_failure(0));
3236 }
3237
3238 TAVOR_TNF_EXIT(tavor_qp_to_reset);
3239 return (DDI_SUCCESS);
3240 }
3241
3242
3243 /*
3244 * tavor_qp_reset2err()
3245 * Context: Can be called from interrupt or base context.
3246 */
3247 static int
tavor_qp_reset2err(tavor_state_t * state,tavor_qphdl_t qp)3248 tavor_qp_reset2err(tavor_state_t *state, tavor_qphdl_t qp)
3249 {
3250 tavor_hw_qpc_t *qpc;
3251 int status;
3252
3253 TAVOR_TNF_ENTER(tavor_qp_reset2err);
3254
3255 ASSERT(MUTEX_HELD(&qp->qp_lock));
3256
3257 /*
3258 * In order to implement the transition from "Reset" directly to the
3259 * "Error" state, it is necessary to first give ownership of the QP
3260 * context to the Tavor hardware. This is accomplished by transitioning
3261 * the QP to "Init" as an intermediate step and then, immediately
3262 * transitioning to "Error".
3263 *
3264 * When this function returns success, the QP context will be owned by
3265 * the Tavor hardware and will be in the "Error" state.
3266 */
3267
3268 /*
3269 * Grab the temporary QPC entry from QP software state
3270 */
3271 qpc = &qp->qpc;
3272
3273 /*
3274 * Fill in the common and/or Tavor-specific fields in the QPC
3275 */
3276 if (qp->qp_is_special) {
3277 qpc->serv_type = TAVOR_QP_MLX;
3278 } else {
3279 qpc->serv_type = qp->qp_serv_type;
3280 }
3281 qpc->pm_state = TAVOR_QP_PMSTATE_MIGRATED;
3282 qpc->de = TAVOR_QP_DESC_EVT_ENABLED;
3283 qpc->sched_q = TAVOR_QP_SCHEDQ_GET(qp->qp_qpnum);
3284 if (qp->qp_is_umap) {
3285 qpc->usr_page = qp->qp_uarpg;
3286 } else {
3287 qpc->usr_page = 0;
3288 }
3289 qpc->pd = qp->qp_pdhdl->pd_pdnum;
3290 qpc->wqe_baseaddr = 0;
3291 qpc->wqe_lkey = qp->qp_mrhdl->mr_lkey;
3292 qpc->ssc = qp->qp_sq_sigtype;
3293 qpc->cqn_snd = qp->qp_sq_cqhdl->cq_cqnum;
3294 qpc->rsc = TAVOR_QP_RQ_ALL_SIGNALED;
3295 qpc->cqn_rcv = qp->qp_rq_cqhdl->cq_cqnum;
3296 qpc->srq_en = qp->qp_srq_en;
3297
3298 if (qp->qp_srq_en == TAVOR_QP_SRQ_ENABLED) {
3299 qpc->srq_number = qp->qp_srqhdl->srq_srqnum;
3300 } else {
3301 qpc->srq_number = 0;
3302 }
3303
3304 /*
3305 * Now fill in the QPC fields which are specific to transport type
3306 */
3307 if (qp->qp_serv_type == TAVOR_QP_UD) {
3308 /* Set the UD parameters to an invalid default */
3309 qpc->qkey = 0;
3310 qpc->pri_addr_path.portnum = 1;
3311 qpc->pri_addr_path.pkey_indx = 0;
3312
3313 } else if (qp->qp_serv_type == TAVOR_QP_RC) {
3314 /* Set the RC parameters to invalid default */
3315 qpc->rre = 0;
3316 qpc->rwe = 0;
3317 qpc->rae = 0;
3318 qpc->pri_addr_path.portnum = 1;
3319 qpc->pri_addr_path.pkey_indx = 0;
3320
3321 } else if (qp->qp_serv_type == TAVOR_QP_UC) {
3322 /* Set the UC parameters to invalid default */
3323 qpc->rwe = 0;
3324 qpc->pri_addr_path.portnum = 1;
3325 qpc->pri_addr_path.pkey_indx = 0;
3326
3327 } else {
3328 /*
3329 * Invalid QP transport type. If we got here then it's a
3330 * warning of a probably serious problem. So print a message
3331 * and return failure
3332 */
3333 TAVOR_WARNING(state, "unknown QP transport type in rst2err");
3334 TNF_PROBE_0(tavor_qp_reset2err_inv_transtype_fail,
3335 TAVOR_TNF_ERROR, "");
3336 TAVOR_TNF_EXIT(tavor_qp_reset2err);
3337 return (ibc_get_ci_failure(0));
3338 }
3339
3340 /*
3341 * Post the RST2INIT_QP command to the Tavor firmware
3342 *
3343 * We do a TAVOR_NOSLEEP here because we are still holding the
3344 * "qp_lock". If we got raised to interrupt level by priority
3345 * inversion, we do not want to block in this routine waiting for
3346 * success.
3347 */
3348 status = tavor_cmn_qp_cmd_post(state, RST2INIT_QP, qpc, qp->qp_qpnum,
3349 0, TAVOR_CMD_NOSLEEP_SPIN);
3350 if (status != TAVOR_CMD_SUCCESS) {
3351 cmn_err(CE_CONT, "Tavor: RST2INIT_QP command failed: %08x\n",
3352 status);
3353 TNF_PROBE_1(tavor_qp_reset2err_rst2init_cmd_fail,
3354 TAVOR_TNF_ERROR, "", tnf_uint, status, status);
3355 TAVOR_TNF_EXIT(tavor_qp_reset2err);
3356 return (ibc_get_ci_failure(0));
3357 }
3358
3359 /*
3360 * Now post the TOERR_QP command to the Tavor firmware
3361 *
3362 * We still do a TAVOR_NOSLEEP here because we are still holding the
3363 * "qp_lock". Note: If this fails (which it really never should),
3364 * it indicates a serious problem in the HW or SW. We try to move
3365 * the QP back to the "Reset" state if possible and print a warning
3366 * message if not. In any case, we return an error here.
3367 */
3368 status = tavor_cmn_qp_cmd_post(state, TOERR_QP, NULL, qp->qp_qpnum,
3369 0, TAVOR_CMD_NOSLEEP_SPIN);
3370 if (status != TAVOR_CMD_SUCCESS) {
3371 cmn_err(CE_CONT, "Tavor: TOERR_QP command failed: %08x\n",
3372 status);
3373 if (tavor_qp_to_reset(state, qp) != DDI_SUCCESS) {
3374 TAVOR_WARNING(state, "failed to reset QP context");
3375 }
3376 TNF_PROBE_1(tavor_qp_reset2err_toerr_cmd_fail,
3377 TAVOR_TNF_ERROR, "", tnf_uint, status, status);
3378 TAVOR_TNF_EXIT(tavor_qp_reset2err);
3379 return (ibc_get_ci_failure(0));
3380 }
3381
3382 TAVOR_TNF_EXIT(tavor_qp_reset2err);
3383 return (DDI_SUCCESS);
3384 }
3385
3386
3387 /*
3388 * tavor_check_rdma_enable_flags()
3389 * Context: Can be called from interrupt or base context.
3390 */
3391 static uint_t
tavor_check_rdma_enable_flags(ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p,tavor_hw_qpc_t * qpc)3392 tavor_check_rdma_enable_flags(ibt_cep_modify_flags_t flags,
3393 ibt_qp_info_t *info_p, tavor_hw_qpc_t *qpc)
3394 {
3395 uint_t opmask = 0;
3396
3397 if (flags & IBT_CEP_SET_RDMA_R) {
3398 qpc->rre = (info_p->qp_flags & IBT_CEP_RDMA_RD) ? 1 : 0;
3399 opmask |= TAVOR_CMD_OP_RRE;
3400 }
3401
3402 if (flags & IBT_CEP_SET_RDMA_W) {
3403 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
3404 opmask |= TAVOR_CMD_OP_RWE;
3405 }
3406
3407 if (flags & IBT_CEP_SET_ATOMIC) {
3408 qpc->rae = (info_p->qp_flags & IBT_CEP_ATOMIC) ? 1 : 0;
3409 opmask |= TAVOR_CMD_OP_RAE;
3410 }
3411
3412 return (opmask);
3413 }
3414
3415 /*
3416 * tavor_qp_validate_resp_rsrc()
3417 * Context: Can be called from interrupt or base context.
3418 */
3419 static int
tavor_qp_validate_resp_rsrc(tavor_state_t * state,ibt_qp_rc_attr_t * rc,uint_t * rra_max)3420 tavor_qp_validate_resp_rsrc(tavor_state_t *state, ibt_qp_rc_attr_t *rc,
3421 uint_t *rra_max)
3422 {
3423 uint_t rdma_ra_in;
3424
3425 rdma_ra_in = rc->rc_rdma_ra_in;
3426
3427 /*
3428 * Check if number of responder resources is too large. Return an
3429 * error if it is
3430 */
3431 if (rdma_ra_in > state->ts_cfg_profile->cp_hca_max_rdma_in_qp) {
3432 return (IBT_INVALID_PARAM);
3433 }
3434
3435 /*
3436 * If the number of responder resources is too small, round it up.
3437 * Then find the next highest power-of-2
3438 */
3439 if (rdma_ra_in == 0) {
3440 rdma_ra_in = 1;
3441 }
3442 if (ISP2(rdma_ra_in)) {
3443 *rra_max = highbit(rdma_ra_in) - 1;
3444 } else {
3445 *rra_max = highbit(rdma_ra_in);
3446 }
3447 return (DDI_SUCCESS);
3448 }
3449
3450
3451 /*
3452 * tavor_qp_validate_init_depth()
3453 * Context: Can be called from interrupt or base context.
3454 */
3455 static int
tavor_qp_validate_init_depth(tavor_state_t * state,ibt_qp_rc_attr_t * rc,uint_t * sra_max)3456 tavor_qp_validate_init_depth(tavor_state_t *state, ibt_qp_rc_attr_t *rc,
3457 uint_t *sra_max)
3458 {
3459 uint_t rdma_ra_out;
3460
3461 rdma_ra_out = rc->rc_rdma_ra_out;
3462
3463 /*
3464 * Check if requested initiator depth is too large. Return an error
3465 * if it is
3466 */
3467 if (rdma_ra_out > state->ts_cfg_profile->cp_hca_max_rdma_out_qp) {
3468 return (IBT_INVALID_PARAM);
3469 }
3470
3471 /*
3472 * If the requested initiator depth is too small, round it up.
3473 * Then find the next highest power-of-2
3474 */
3475 if (rdma_ra_out == 0) {
3476 rdma_ra_out = 1;
3477 }
3478 if (ISP2(rdma_ra_out)) {
3479 *sra_max = highbit(rdma_ra_out) - 1;
3480 } else {
3481 *sra_max = highbit(rdma_ra_out);
3482 }
3483 return (DDI_SUCCESS);
3484 }
3485
3486
3487 /*
3488 * tavor_qp_validate_mtu()
3489 * Context: Can be called from interrupt or base context.
3490 */
3491 static int
tavor_qp_validate_mtu(tavor_state_t * state,uint_t mtu)3492 tavor_qp_validate_mtu(tavor_state_t *state, uint_t mtu)
3493 {
3494 /*
3495 * Check for invalid MTU values (i.e. zero or any value larger than
3496 * the HCA's port maximum).
3497 */
3498 if ((mtu == 0) || (mtu > state->ts_cfg_profile->cp_max_mtu)) {
3499 return (IBT_HCA_PORT_MTU_EXCEEDED);
3500 }
3501 return (DDI_SUCCESS);
3502 }
3503