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