5255 uts shouldn't open-code ISP2
[illumos-gate.git] / usr / src / uts / common / io / ib / adapters / hermon / hermon_qpmod.c
blob77c2aa4f4a2226d0d3f9b900b66575233e00eb27
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
27 * hermon_qpmod.c
28 * Hermon Queue Pair Modify Routines
30 * This contains all the routines necessary to implement the
31 * ModifyQP() verb. This includes all the code for legal
32 * transitions to and from Reset, Init, RTR, RTS, SQD, SQErr,
33 * and Error.
36 #include <sys/sysmacros.h>
37 #include <sys/types.h>
38 #include <sys/conf.h>
39 #include <sys/ddi.h>
40 #include <sys/sunddi.h>
41 #include <sys/modctl.h>
42 #include <sys/bitmap.h>
44 #include <sys/ib/adapters/hermon/hermon.h>
45 #include <sys/ib/ib_pkt_hdrs.h>
47 static int hermon_qp_reset2init(hermon_state_t *state, hermon_qphdl_t qp,
48 ibt_qp_info_t *info_p);
49 static int hermon_qp_init2init(hermon_state_t *state, hermon_qphdl_t qp,
50 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
51 static int hermon_qp_init2rtr(hermon_state_t *state, hermon_qphdl_t qp,
52 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
53 static int hermon_qp_rtr2rts(hermon_state_t *state, hermon_qphdl_t qp,
54 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
55 static int hermon_qp_rts2rts(hermon_state_t *state, hermon_qphdl_t qp,
56 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
57 #ifdef HERMON_NOTNOW
58 static int hermon_qp_rts2sqd(hermon_state_t *state, hermon_qphdl_t qp,
59 ibt_cep_modify_flags_t flags);
60 #endif
61 static int hermon_qp_sqd2rts(hermon_state_t *state, hermon_qphdl_t qp,
62 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
63 static int hermon_qp_sqd2sqd(hermon_state_t *state, hermon_qphdl_t qp,
64 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
65 static int hermon_qp_sqerr2rts(hermon_state_t *state, hermon_qphdl_t qp,
66 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
67 static int hermon_qp_to_error(hermon_state_t *state, hermon_qphdl_t qp);
68 static int hermon_qp_reset2err(hermon_state_t *state, hermon_qphdl_t qp);
70 static uint_t hermon_check_rdma_enable_flags(ibt_cep_modify_flags_t flags,
71 ibt_qp_info_t *info_p, hermon_hw_qpc_t *qpc);
72 static int hermon_qp_validate_resp_rsrc(hermon_state_t *state,
73 ibt_qp_rc_attr_t *rc, uint_t *rra_max);
74 static int hermon_qp_validate_init_depth(hermon_state_t *state,
75 ibt_qp_rc_attr_t *rc, uint_t *sra_max);
76 static int hermon_qp_validate_mtu(hermon_state_t *state, uint_t mtu);
79 * hermon_qp_modify()
80 * Context: Can be called from interrupt or base context.
82 /* ARGSUSED */
83 int
84 hermon_qp_modify(hermon_state_t *state, hermon_qphdl_t qp,
85 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p,
86 ibt_queue_sizes_t *actual_sz)
88 ibt_cep_state_t cur_state, mod_state;
89 ibt_cep_modify_flags_t okflags;
90 int status;
93 * TODO add support for SUSPEND and RESUME
97 * Lock the QP so that we can modify it atomically. After grabbing
98 * the lock, get the current QP state. We will use this current QP
99 * state to determine the legal transitions (and the checks that need
100 * to be performed.)
101 * Below is a case for every possible QP state. In each case, we
102 * check that no flags are set which are not valid for the possible
103 * transitions from that state. If these tests pass and the
104 * state transition we are attempting is legal, then we call one
105 * of the helper functions. Each of these functions does some
106 * additional setup before posting the firmware command for the
107 * appropriate state transition.
109 mutex_enter(&qp->qp_lock);
112 * Verify that the transport type matches between the serv_type and the
113 * qp_trans. A caller to IBT must specify the qp_trans field as
114 * IBT_UD_SRV, IBT_RC_SRV, or IBT_UC_SRV, depending on the QP. We
115 * check here that the correct value was specified, based on our
116 * understanding of the QP serv type.
118 * Because callers specify part of a 'union' based on what QP type they
119 * think they're working with, this ensures that we do not pickup bogus
120 * data if the caller thought they were working with a different QP
121 * type.
123 if (!(HERMON_QP_TYPE_VALID(info_p->qp_trans, qp->qp_serv_type))) {
124 mutex_exit(&qp->qp_lock);
125 return (IBT_QP_SRV_TYPE_INVALID);
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 an Hermon 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").
136 mod_state = info_p->qp_state;
138 if (flags & IBT_CEP_SET_RTR_RTS) {
139 cur_state = HERMON_QP_RTR; /* Ready to Receive */
141 } else if ((flags & IBT_CEP_SET_STATE) &&
142 (mod_state == IBT_STATE_RTS)) {
144 /* Convert the current IBTF QP state to an Hermon QP state */
145 switch (info_p->qp_current_state) {
146 case IBT_STATE_RTR:
147 cur_state = HERMON_QP_RTR; /* Ready to Receive */
148 break;
149 case IBT_STATE_RTS:
150 cur_state = HERMON_QP_RTS; /* Ready to Send */
151 break;
152 case IBT_STATE_SQE:
153 cur_state = HERMON_QP_SQERR; /* Send Queue Error */
154 break;
155 case IBT_STATE_SQD:
156 cur_state = HERMON_QP_SQD; /* SQ Drained */
157 break;
158 default:
159 mutex_exit(&qp->qp_lock);
160 return (IBT_QP_STATE_INVALID);
162 } else {
163 cur_state = qp->qp_state;
166 switch (cur_state) {
167 case HERMON_QP_RESET:
168 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_RESET_INIT |
169 IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W |
170 IBT_CEP_SET_ATOMIC | IBT_CEP_SET_PKEY_IX |
171 IBT_CEP_SET_PORT | IBT_CEP_SET_QKEY);
174 * Check for attempts to modify invalid attributes from the
175 * "Reset" state
177 if (flags & ~okflags) {
178 mutex_exit(&qp->qp_lock);
179 status = IBT_QP_ATTR_RO;
180 goto qpmod_fail;
184 * Verify state transition is to either "Init", back to
185 * "Reset", or to "Error".
187 if ((flags & IBT_CEP_SET_RESET_INIT) &&
188 (flags & IBT_CEP_SET_STATE) &&
189 (mod_state != IBT_STATE_INIT)) {
190 /* Invalid transition - ambiguous flags */
191 mutex_exit(&qp->qp_lock);
192 status = IBT_QP_STATE_INVALID;
193 goto qpmod_fail;
195 } else if ((flags & IBT_CEP_SET_RESET_INIT) ||
196 ((flags & IBT_CEP_SET_STATE) &&
197 (mod_state == IBT_STATE_INIT))) {
199 * Attempt to transition from "Reset" to "Init"
201 status = hermon_qp_reset2init(state, qp, info_p);
202 if (status != DDI_SUCCESS) {
203 mutex_exit(&qp->qp_lock);
204 goto qpmod_fail;
206 qp->qp_state = HERMON_QP_INIT;
207 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_INIT);
209 } else if ((flags & IBT_CEP_SET_STATE) &&
210 (mod_state == IBT_STATE_RESET)) {
212 * Attempt to transition from "Reset" back to "Reset"
213 * Nothing to do here really... just drop the lock
214 * and return success. The qp->qp_state should
215 * already be set to HERMON_QP_RESET.
217 * Note: We return here because we do not want to fall
218 * through to the hermon_wrid_from_reset_handling()
219 * routine below (since we are not really moving
220 * _out_ of the "Reset" state.
222 mutex_exit(&qp->qp_lock);
223 return (DDI_SUCCESS);
225 } else if ((flags & IBT_CEP_SET_STATE) &&
226 (mod_state == IBT_STATE_ERROR)) {
228 * Attempt to transition from "Reset" to "Error"
230 status = hermon_qp_reset2err(state, qp);
231 if (status != DDI_SUCCESS) {
232 mutex_exit(&qp->qp_lock);
233 goto qpmod_fail;
235 qp->qp_state = HERMON_QP_ERR;
236 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_ERR);
238 } else {
239 /* Invalid transition - return error */
240 mutex_exit(&qp->qp_lock);
241 status = IBT_QP_STATE_INVALID;
242 goto qpmod_fail;
246 * Do any additional handling necessary here for the transition
247 * from the "Reset" state (e.g. re-initialize the workQ WRID
248 * lists). Note: If hermon_wrid_from_reset_handling() fails,
249 * then we attempt to transition the QP back to the "Reset"
250 * state. If that fails, then it is an indication of a serious
251 * problem (either HW or SW). So we print out a warning
252 * message and return failure.
254 status = hermon_wrid_from_reset_handling(state, qp);
255 if (status != DDI_SUCCESS) {
256 if (hermon_qp_to_reset(state, qp) != DDI_SUCCESS) {
257 HERMON_WARNING(state, "failed to reset QP");
259 qp->qp_state = HERMON_QP_RESET;
260 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RESET);
262 mutex_exit(&qp->qp_lock);
263 goto qpmod_fail;
265 break;
267 case HERMON_QP_INIT:
268 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_INIT_RTR |
269 IBT_CEP_SET_ADDS_VECT | IBT_CEP_SET_RDMARA_IN |
270 IBT_CEP_SET_MIN_RNR_NAK | IBT_CEP_SET_ALT_PATH |
271 IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W |
272 IBT_CEP_SET_ATOMIC | IBT_CEP_SET_PKEY_IX |
273 IBT_CEP_SET_QKEY | IBT_CEP_SET_PORT);
276 * Check for attempts to modify invalid attributes from the
277 * "Init" state
279 if (flags & ~okflags) {
280 mutex_exit(&qp->qp_lock);
281 status = IBT_QP_ATTR_RO;
282 goto qpmod_fail;
286 * Verify state transition is to either "RTR", back to "Init",
287 * to "Reset", or to "Error"
289 if ((flags & IBT_CEP_SET_INIT_RTR) &&
290 (flags & IBT_CEP_SET_STATE) &&
291 (mod_state != IBT_STATE_RTR)) {
292 /* Invalid transition - ambiguous flags */
293 mutex_exit(&qp->qp_lock);
294 status = IBT_QP_STATE_INVALID;
295 goto qpmod_fail;
297 } else if ((flags & IBT_CEP_SET_INIT_RTR) ||
298 ((flags & IBT_CEP_SET_STATE) &&
299 (mod_state == IBT_STATE_RTR))) {
301 * Attempt to transition from "Init" to "RTR"
303 status = hermon_qp_init2rtr(state, qp, flags, info_p);
304 if (status != DDI_SUCCESS) {
305 mutex_exit(&qp->qp_lock);
306 goto qpmod_fail;
308 qp->qp_state = HERMON_QP_RTR;
309 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RTR);
311 } else if ((flags & IBT_CEP_SET_STATE) &&
312 (mod_state == IBT_STATE_INIT)) {
314 * Attempt to transition from "Init" to "Init"
316 status = hermon_qp_init2init(state, qp, flags, info_p);
317 if (status != DDI_SUCCESS) {
318 mutex_exit(&qp->qp_lock);
319 goto qpmod_fail;
321 qp->qp_state = HERMON_QP_INIT;
322 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_INIT);
324 } else if ((flags & IBT_CEP_SET_STATE) &&
325 (mod_state == IBT_STATE_RESET)) {
327 * Attempt to transition from "Init" to "Reset"
329 status = hermon_qp_to_reset(state, qp);
330 if (status != DDI_SUCCESS) {
331 mutex_exit(&qp->qp_lock);
332 goto qpmod_fail;
334 qp->qp_state = HERMON_QP_RESET;
335 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RESET);
338 * Do any additional handling necessary for the
339 * transition _to_ the "Reset" state (e.g. update the
340 * workQ WRID lists)
342 status = hermon_wrid_to_reset_handling(state, qp);
343 if (status != IBT_SUCCESS) {
344 mutex_exit(&qp->qp_lock);
345 goto qpmod_fail;
348 } else if ((flags & IBT_CEP_SET_STATE) &&
349 (mod_state == IBT_STATE_ERROR)) {
351 * Attempt to transition from "Init" to "Error"
353 status = hermon_qp_to_error(state, qp);
354 if (status != DDI_SUCCESS) {
355 mutex_exit(&qp->qp_lock);
356 goto qpmod_fail;
358 qp->qp_state = HERMON_QP_ERR;
359 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_ERR);
361 } else {
362 /* Invalid transition - return error */
363 mutex_exit(&qp->qp_lock);
364 status = IBT_QP_STATE_INVALID;
365 goto qpmod_fail;
367 break;
369 case HERMON_QP_RTR:
370 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_RTR_RTS |
371 IBT_CEP_SET_TIMEOUT | IBT_CEP_SET_RETRY |
372 IBT_CEP_SET_RNR_NAK_RETRY | IBT_CEP_SET_RDMARA_OUT |
373 IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W |
374 IBT_CEP_SET_ATOMIC | IBT_CEP_SET_QKEY |
375 IBT_CEP_SET_ALT_PATH | IBT_CEP_SET_MIG |
376 IBT_CEP_SET_MIN_RNR_NAK);
379 * Check for attempts to modify invalid attributes from the
380 * "RTR" state
382 if (flags & ~okflags) {
383 mutex_exit(&qp->qp_lock);
384 status = IBT_QP_ATTR_RO;
385 goto qpmod_fail;
389 * Verify state transition is to either "RTS", "Reset",
390 * or "Error"
392 if ((flags & IBT_CEP_SET_RTR_RTS) &&
393 (flags & IBT_CEP_SET_STATE) &&
394 (mod_state != IBT_STATE_RTS)) {
395 /* Invalid transition - ambiguous flags */
396 mutex_exit(&qp->qp_lock);
397 status = IBT_QP_STATE_INVALID;
398 goto qpmod_fail;
400 } else if ((flags & IBT_CEP_SET_RTR_RTS) ||
401 ((flags & IBT_CEP_SET_STATE) &&
402 (mod_state == IBT_STATE_RTS))) {
404 * Attempt to transition from "RTR" to "RTS"
406 status = hermon_qp_rtr2rts(state, qp, flags, info_p);
407 if (status != DDI_SUCCESS) {
408 mutex_exit(&qp->qp_lock);
409 goto qpmod_fail;
411 qp->qp_state = HERMON_QP_RTS;
412 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RTS);
414 } else if ((flags & IBT_CEP_SET_STATE) &&
415 (mod_state == IBT_STATE_RESET)) {
417 * Attempt to transition from "RTR" to "Reset"
419 status = hermon_qp_to_reset(state, qp);
420 if (status != DDI_SUCCESS) {
421 mutex_exit(&qp->qp_lock);
422 goto qpmod_fail;
424 qp->qp_state = HERMON_QP_RESET;
425 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RESET);
428 * Do any additional handling necessary for the
429 * transition _to_ the "Reset" state (e.g. update the
430 * workQ WRID lists)
432 status = hermon_wrid_to_reset_handling(state, qp);
433 if (status != IBT_SUCCESS) {
434 mutex_exit(&qp->qp_lock);
435 goto qpmod_fail;
438 } else if ((flags & IBT_CEP_SET_STATE) &&
439 (mod_state == IBT_STATE_ERROR)) {
441 * Attempt to transition from "RTR" to "Error"
443 status = hermon_qp_to_error(state, qp);
444 if (status != DDI_SUCCESS) {
445 mutex_exit(&qp->qp_lock);
446 goto qpmod_fail;
448 qp->qp_state = HERMON_QP_ERR;
449 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_ERR);
451 } else {
452 /* Invalid transition - return error */
453 mutex_exit(&qp->qp_lock);
454 status = IBT_QP_STATE_INVALID;
455 goto qpmod_fail;
457 break;
459 case HERMON_QP_RTS:
460 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_RDMA_R |
461 IBT_CEP_SET_RDMA_W | IBT_CEP_SET_ATOMIC |
462 IBT_CEP_SET_QKEY | IBT_CEP_SET_ALT_PATH |
463 IBT_CEP_SET_MIG | IBT_CEP_SET_MIN_RNR_NAK |
464 IBT_CEP_SET_SQD_EVENT);
467 * Check for attempts to modify invalid attributes from the
468 * "RTS" state
470 if (flags & ~okflags) {
471 mutex_exit(&qp->qp_lock);
472 status = IBT_QP_ATTR_RO;
473 goto qpmod_fail;
477 * Verify state transition is to either "RTS", "SQD", "Reset",
478 * or "Error"
480 if ((flags & IBT_CEP_SET_STATE) &&
481 (mod_state == IBT_STATE_RTS)) {
483 * Attempt to transition from "RTS" to "RTS"
485 status = hermon_qp_rts2rts(state, qp, flags, info_p);
486 if (status != DDI_SUCCESS) {
487 mutex_exit(&qp->qp_lock);
488 goto qpmod_fail;
490 qp->qp_state = HERMON_QP_RTS;
491 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RTS);
493 } else if ((flags & IBT_CEP_SET_STATE) &&
494 (mod_state == IBT_STATE_SQD)) {
495 #ifdef HERMON_NOTNOW
497 * Attempt to transition from "RTS" to "SQD"
499 status = hermon_qp_rts2sqd(state, qp, flags);
500 if (status != DDI_SUCCESS) {
501 mutex_exit(&qp->qp_lock);
502 goto qpmod_fail;
504 qp->qp_state = HERMON_QP_SQD;
505 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_SQD);
506 #else
507 /* hack because of the lack of fw support for SQD */
508 mutex_exit(&qp->qp_lock);
509 status = IBT_QP_STATE_INVALID;
510 goto qpmod_fail;
511 #endif
513 } else if ((flags & IBT_CEP_SET_STATE) &&
514 (mod_state == IBT_STATE_RESET)) {
516 * Attempt to transition from "RTS" to "Reset"
518 status = hermon_qp_to_reset(state, qp);
519 if (status != DDI_SUCCESS) {
520 mutex_exit(&qp->qp_lock);
521 goto qpmod_fail;
523 qp->qp_state = HERMON_QP_RESET;
524 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RESET);
527 * Do any additional handling necessary for the
528 * transition _to_ the "Reset" state (e.g. update the
529 * workQ WRID lists)
531 status = hermon_wrid_to_reset_handling(state, qp);
532 if (status != IBT_SUCCESS) {
533 mutex_exit(&qp->qp_lock);
534 goto qpmod_fail;
537 } else if ((flags & IBT_CEP_SET_STATE) &&
538 (mod_state == IBT_STATE_ERROR)) {
540 * Attempt to transition from "RTS" to "Error"
542 status = hermon_qp_to_error(state, qp);
543 if (status != DDI_SUCCESS) {
544 mutex_exit(&qp->qp_lock);
545 goto qpmod_fail;
547 qp->qp_state = HERMON_QP_ERR;
548 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_ERR);
550 } else {
551 /* Invalid transition - return error */
552 mutex_exit(&qp->qp_lock);
553 status = IBT_QP_STATE_INVALID;
554 goto qpmod_fail;
556 break;
558 case HERMON_QP_SQERR:
559 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_RDMA_R |
560 IBT_CEP_SET_RDMA_W | IBT_CEP_SET_ATOMIC |
561 IBT_CEP_SET_QKEY | IBT_CEP_SET_MIN_RNR_NAK);
564 * Check for attempts to modify invalid attributes from the
565 * "SQErr" state
567 if (flags & ~okflags) {
568 mutex_exit(&qp->qp_lock);
569 status = IBT_QP_ATTR_RO;
570 goto qpmod_fail;
574 * Verify state transition is to either "RTS", "Reset", or
575 * "Error"
577 if ((flags & IBT_CEP_SET_STATE) &&
578 (mod_state == IBT_STATE_RTS)) {
580 * Attempt to transition from "SQErr" to "RTS"
582 status = hermon_qp_sqerr2rts(state, qp, flags, info_p);
583 if (status != DDI_SUCCESS) {
584 mutex_exit(&qp->qp_lock);
585 goto qpmod_fail;
587 qp->qp_state = HERMON_QP_RTS;
588 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RTS);
590 } else if ((flags & IBT_CEP_SET_STATE) &&
591 (mod_state == IBT_STATE_RESET)) {
593 * Attempt to transition from "SQErr" to "Reset"
595 status = hermon_qp_to_reset(state, qp);
596 if (status != DDI_SUCCESS) {
597 mutex_exit(&qp->qp_lock);
598 goto qpmod_fail;
600 qp->qp_state = HERMON_QP_RESET;
601 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RESET);
604 * Do any additional handling necessary for the
605 * transition _to_ the "Reset" state (e.g. update the
606 * workQ WRID lists)
608 status = hermon_wrid_to_reset_handling(state, qp);
609 if (status != IBT_SUCCESS) {
610 mutex_exit(&qp->qp_lock);
611 goto qpmod_fail;
614 } else if ((flags & IBT_CEP_SET_STATE) &&
615 (mod_state == IBT_STATE_ERROR)) {
617 * Attempt to transition from "SQErr" to "Error"
619 status = hermon_qp_to_error(state, qp);
620 if (status != DDI_SUCCESS) {
621 mutex_exit(&qp->qp_lock);
622 goto qpmod_fail;
624 qp->qp_state = HERMON_QP_ERR;
625 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_ERR);
627 } else {
628 /* Invalid transition - return error */
629 mutex_exit(&qp->qp_lock);
630 status = IBT_QP_STATE_INVALID;
631 goto qpmod_fail;
633 break;
635 case HERMON_QP_SQD:
636 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_ADDS_VECT |
637 IBT_CEP_SET_ALT_PATH | IBT_CEP_SET_MIG |
638 IBT_CEP_SET_RDMARA_OUT | IBT_CEP_SET_RDMARA_IN |
639 IBT_CEP_SET_QKEY | IBT_CEP_SET_PKEY_IX |
640 IBT_CEP_SET_TIMEOUT | IBT_CEP_SET_RETRY |
641 IBT_CEP_SET_RNR_NAK_RETRY | IBT_CEP_SET_PORT |
642 IBT_CEP_SET_MIN_RNR_NAK | IBT_CEP_SET_RDMA_R |
643 IBT_CEP_SET_RDMA_W | IBT_CEP_SET_ATOMIC);
646 * Check for attempts to modify invalid attributes from the
647 * "SQD" state
649 if (flags & ~okflags) {
650 mutex_exit(&qp->qp_lock);
651 status = IBT_QP_ATTR_RO;
652 goto qpmod_fail;
656 * Verify state transition is to either "SQD", "RTS", "Reset",
657 * or "Error"
660 if ((flags & IBT_CEP_SET_STATE) &&
661 (mod_state == IBT_STATE_SQD)) {
663 * Attempt to transition from "SQD" to "SQD"
665 status = hermon_qp_sqd2sqd(state, qp, flags, info_p);
666 if (status != DDI_SUCCESS) {
667 mutex_exit(&qp->qp_lock);
668 goto qpmod_fail;
670 qp->qp_state = HERMON_QP_SQD;
671 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_SQD);
673 } else if ((flags & IBT_CEP_SET_STATE) &&
674 (mod_state == IBT_STATE_RTS)) {
676 * If still draining SQ, then fail transition attempt
677 * to RTS, even though this is now done is two steps
678 * (see below) if the consumer has tried this before
679 * it's drained, let him fail and wait appropriately
681 if (qp->qp_sqd_still_draining) {
682 mutex_exit(&qp->qp_lock);
683 goto qpmod_fail;
686 * IBA 1.2 has changed - most/all the things that were
687 * done in SQD2RTS can be done in SQD2SQD. So make this
688 * a 2-step process. First, set any attributes requsted
689 * w/ SQD2SQD, but no real transition.
691 * First, Attempt to transition from "SQD" to "SQD"
693 status = hermon_qp_sqd2sqd(state, qp, flags, info_p);
694 if (status != DDI_SUCCESS) {
695 mutex_exit(&qp->qp_lock);
696 goto qpmod_fail;
698 qp->qp_state = HERMON_QP_SQD;
699 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_SQD);
702 * The, attempt to transition from "SQD" to "RTS", but
703 * request only the state transition, no attributes
706 status = hermon_qp_sqd2rts(state, qp,
707 IBT_CEP_SET_STATE, info_p);
708 if (status != DDI_SUCCESS) {
709 mutex_exit(&qp->qp_lock);
710 goto qpmod_fail;
712 qp->qp_state = HERMON_QP_RTS;
713 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RTS);
715 } else if ((flags & IBT_CEP_SET_STATE) &&
716 (mod_state == IBT_STATE_RESET)) {
718 * Attempt to transition from "SQD" to "Reset"
720 status = hermon_qp_to_reset(state, qp);
721 if (status != DDI_SUCCESS) {
722 mutex_exit(&qp->qp_lock);
723 goto qpmod_fail;
725 qp->qp_state = HERMON_QP_RESET;
726 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RESET);
729 * Do any additional handling necessary for the
730 * transition _to_ the "Reset" state (e.g. update the
731 * workQ WRID lists)
733 status = hermon_wrid_to_reset_handling(state, qp);
734 if (status != IBT_SUCCESS) {
735 mutex_exit(&qp->qp_lock);
736 goto qpmod_fail;
739 } else if ((flags & IBT_CEP_SET_STATE) &&
740 (mod_state == IBT_STATE_ERROR)) {
742 * Attempt to transition from "SQD" to "Error"
744 status = hermon_qp_to_error(state, qp);
745 if (status != DDI_SUCCESS) {
746 mutex_exit(&qp->qp_lock);
747 goto qpmod_fail;
749 qp->qp_state = HERMON_QP_ERR;
750 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_ERR);
752 } else {
753 /* Invalid transition - return error */
754 mutex_exit(&qp->qp_lock);
755 status = IBT_QP_STATE_INVALID;
756 goto qpmod_fail;
758 break;
760 case HERMON_QP_ERR:
762 * Verify state transition is to either "Reset" or back to
763 * "Error"
765 if ((flags & IBT_CEP_SET_STATE) &&
766 (mod_state == IBT_STATE_RESET)) {
768 * Attempt to transition from "Error" to "Reset"
770 status = hermon_qp_to_reset(state, qp);
771 if (status != DDI_SUCCESS) {
772 mutex_exit(&qp->qp_lock);
773 goto qpmod_fail;
775 qp->qp_state = HERMON_QP_RESET;
776 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RESET);
779 * Do any additional handling necessary for the
780 * transition _to_ the "Reset" state (e.g. update the
781 * workQ WRID lists)
783 status = hermon_wrid_to_reset_handling(state, qp);
784 if (status != IBT_SUCCESS) {
785 mutex_exit(&qp->qp_lock);
786 goto qpmod_fail;
789 } else if ((flags & IBT_CEP_SET_STATE) &&
790 (mod_state == IBT_STATE_ERROR)) {
792 * Attempt to transition from "Error" back to "Error"
793 * Nothing to do here really... just drop the lock
794 * and return success. The qp->qp_state should
795 * already be set to HERMON_QP_ERR.
798 mutex_exit(&qp->qp_lock);
799 return (DDI_SUCCESS);
801 } else {
802 /* Invalid transition - return error */
803 mutex_exit(&qp->qp_lock);
804 status = IBT_QP_STATE_INVALID;
805 goto qpmod_fail;
807 break;
809 default:
811 * Invalid QP state. If we got here then it's a warning of
812 * a probably serious problem. So print a message and return
813 * failure
815 mutex_exit(&qp->qp_lock);
816 HERMON_WARNING(state, "unknown QP state in modify");
817 status = IBT_QP_STATE_INVALID;
818 goto qpmod_fail;
821 mutex_exit(&qp->qp_lock);
822 return (DDI_SUCCESS);
824 qpmod_fail:
825 return (status);
830 * hermon_qp_reset2init()
831 * Context: Can be called from interrupt or base context.
833 static int
834 hermon_qp_reset2init(hermon_state_t *state, hermon_qphdl_t qp,
835 ibt_qp_info_t *info_p)
837 hermon_hw_qpc_t *qpc;
838 ibt_qp_rc_attr_t *rc;
839 ibt_qp_ud_attr_t *ud;
840 ibt_qp_uc_attr_t *uc;
841 uint_t portnum, pkeyindx;
842 int status;
843 uint32_t cqnmask;
844 int qp_srq_en;
846 ASSERT(MUTEX_HELD(&qp->qp_lock));
849 * Grab the temporary QPC entry from QP software state
851 qpc = &qp->qpc;
854 * Fill in the common fields in the QPC
857 if (qp->qp_is_special) {
858 qpc->serv_type = HERMON_QP_MLX;
859 } else {
860 qpc->serv_type = qp->qp_serv_type;
862 qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
864 qpc->pd = qp->qp_pdhdl->pd_pdnum;
866 qpc->log_sq_stride = qp->qp_sq_log_wqesz - 4;
867 qpc->log_rq_stride = qp->qp_rq_log_wqesz - 4;
868 qpc->sq_no_prefetch = qp->qp_no_prefetch;
869 qpc->log_sq_size = highbit(qp->qp_sq_bufsz) - 1;
870 qpc->log_rq_size = highbit(qp->qp_rq_bufsz) - 1;
872 qpc->usr_page = qp->qp_uarpg;
874 cqnmask = (1 << state->hs_cfg_profile->cp_log_num_cq) - 1;
875 qpc->cqn_snd =
876 (qp->qp_sq_cqhdl == NULL) ? 0 : qp->qp_sq_cqhdl->cq_cqnum & cqnmask;
877 qpc->page_offs = qp->qp_wqinfo.qa_pgoffs >> 6;
878 qpc->cqn_rcv =
879 (qp->qp_rq_cqhdl == NULL) ? 0 : qp->qp_rq_cqhdl->cq_cqnum & cqnmask;
881 /* dbr is now an address, not an index */
882 qpc->dbr_addrh = ((uint64_t)qp->qp_rq_pdbr >> 32);
883 qpc->dbr_addrl = ((uint64_t)qp->qp_rq_pdbr & 0xFFFFFFFC) >> 2;
884 qpc->sq_wqe_counter = 0;
885 qpc->rq_wqe_counter = 0;
887 * HERMON:
888 * qpc->wqe_baseaddr is replaced by LKey from the cMPT, and
889 * page_offset, mtt_base_addr_h/l, and log2_page_size will
890 * be used to map the WQE buffer
891 * NOTE that the cMPT is created implicitly when the QP is
892 * transitioned from reset to init
894 qpc->log2_pgsz = qp->qp_mrhdl->mr_log2_pgsz;
895 qpc->mtt_base_addrl = (qp->qp_mrhdl->mr_mttaddr) >> 3;
896 qpc->mtt_base_addrh = (uint32_t)((qp->qp_mrhdl->mr_mttaddr >> 32) &
897 0xFF);
898 qp_srq_en = (qp->qp_alloc_flags & IBT_QP_USES_SRQ) != 0;
899 qpc->srq_en = qp_srq_en;
901 if (qp_srq_en) {
902 qpc->srq_number = qp->qp_srqhdl->srq_srqnum;
903 } else {
904 qpc->srq_number = 0;
908 * Fast Registration Work Requests and Reserved Lkey are enabled
909 * with the single IBT bit stored in qp_rlky.
911 qpc->fre = qp->qp_rlky;
912 qpc->rlky = qp->qp_rlky;
914 /* 1.2 verbs extensions disabled for now */
915 qpc->header_sep = 0; /* disable header separation for now */
916 qpc->rss = qp->qp_alloc_flags & IBT_QP_USES_RSS ? 1 : 0;
917 qpc->inline_scatter = 0; /* disable inline scatter for now */
920 * Now fill in the QPC fields which are specific to transport type
922 if (qp->qp_type == IBT_UD_RQP) {
923 int my_fc_id_idx, exch_base;
925 ud = &info_p->qp_transport.ud;
927 /* Set the QKey */
928 qpc->qkey = ud->ud_qkey;
931 * Set MTU and message max. Hermon checks the QPC
932 * MTU settings rather than just the port MTU,
933 * so set it to maximum size.
935 qpc->mtu = HERMON_MAX_MTU;
936 if (qp->qp_uses_lso)
937 qpc->msg_max = state->hs_devlim.log_max_gso_sz;
938 else if (qp->qp_is_special)
939 qpc->msg_max = HERMON_MAX_MTU + 6;
940 else
941 qpc->msg_max = HERMON_QP_LOG_MAX_MSGSZ;
943 /* Check for valid port number and fill it in */
944 portnum = ud->ud_port;
945 if (hermon_portnum_is_valid(state, portnum)) {
946 qp->qp_portnum = portnum - 1;
947 qpc->pri_addr_path.sched_q =
948 HERMON_QP_SCHEDQ_GET(portnum - 1,
949 0, qp->qp_is_special);
950 } else {
951 return (IBT_HCA_PORT_INVALID);
955 /* Check for valid PKey index and fill it in */
956 pkeyindx = ud->ud_pkey_ix;
957 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
958 qpc->pri_addr_path.pkey_indx = pkeyindx;
959 qp->qp_pkeyindx = pkeyindx;
960 } else {
961 return (IBT_PKEY_IX_ILLEGAL);
964 /* fill in the RSS fields */
965 if (qpc->rss) {
966 struct hermon_hw_rss_s *rssp;
967 ibt_rss_flags_t flags = ud->ud_rss.rss_flags;
969 rssp = (struct hermon_hw_rss_s *)&qpc->pri_addr_path;
970 rssp->log2_tbl_sz = ud->ud_rss.rss_log2_table;
971 rssp->base_qpn = ud->ud_rss.rss_base_qpn;
972 rssp->default_qpn = ud->ud_rss.rss_def_qpn;
973 if (flags & IBT_RSS_ALG_XOR)
974 rssp->hash_fn = 0; /* XOR Hash Function */
975 else if (flags & IBT_RSS_ALG_TPL)
976 rssp->hash_fn = 1; /* Toeplitz Hash Fn */
977 else
978 return (IBT_INVALID_PARAM);
979 rssp->ipv4 = (flags & IBT_RSS_HASH_IPV4) != 0;
980 rssp->tcp_ipv4 = (flags & IBT_RSS_HASH_TCP_IPV4) != 0;
981 rssp->ipv6 = (flags & IBT_RSS_HASH_IPV6) != 0;
982 rssp->tcp_ipv4 = (flags & IBT_RSS_HASH_TCP_IPV6) != 0;
983 bcopy(ud->ud_rss.rss_toe_key, rssp->rss_key, 40);
984 } else if (qp->qp_serv_type == HERMON_QP_RFCI) {
985 status = hermon_fcoib_set_id(state, portnum,
986 qp->qp_qpnum, ud->ud_fc.fc_src_id);
987 if (status != DDI_SUCCESS)
988 return (status);
989 qp->qp_fc_attr = ud->ud_fc;
990 } else if (qp->qp_serv_type == HERMON_QP_FEXCH) {
991 my_fc_id_idx = hermon_fcoib_get_id_idx(state,
992 portnum, &ud->ud_fc);
993 if (my_fc_id_idx == -1)
994 return (IBT_INVALID_PARAM);
995 qpc->my_fc_id_idx = my_fc_id_idx;
997 status = hermon_fcoib_fexch_mkey_init(state,
998 qp->qp_pdhdl, ud->ud_fc.fc_hca_port,
999 qp->qp_qpnum, HERMON_CMD_NOSLEEP_SPIN);
1000 if (status != DDI_SUCCESS)
1001 return (status);
1002 qp->qp_fc_attr = ud->ud_fc;
1003 } else if (qp->qp_serv_type == HERMON_QP_FCMND) {
1004 my_fc_id_idx = hermon_fcoib_get_id_idx(state,
1005 portnum, &ud->ud_fc);
1006 if (my_fc_id_idx == -1)
1007 return (IBT_INVALID_PARAM);
1008 qpc->my_fc_id_idx = my_fc_id_idx;
1009 exch_base = hermon_fcoib_check_exch_base_off(state,
1010 portnum, &ud->ud_fc);
1011 if (exch_base == -1)
1012 return (IBT_INVALID_PARAM);
1013 qpc->exch_base = exch_base;
1014 qpc->exch_size = ud->ud_fc.fc_exch_log2_sz;
1015 qp->qp_fc_attr = ud->ud_fc;
1018 } else if (qp->qp_serv_type == HERMON_QP_RC) {
1019 rc = &info_p->qp_transport.rc;
1021 /* Set the RDMA (recv) enable/disable flags */
1022 qpc->rre = (info_p->qp_flags & IBT_CEP_RDMA_RD) ? 1 : 0;
1023 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
1024 qpc->rae = (info_p->qp_flags & IBT_CEP_ATOMIC) ? 1 : 0;
1026 /* Check for valid port number and fill it in */
1027 portnum = rc->rc_path.cep_hca_port_num;
1028 if (hermon_portnum_is_valid(state, portnum)) {
1029 qp->qp_portnum = portnum - 1;
1030 qpc->pri_addr_path.sched_q =
1031 HERMON_QP_SCHEDQ_GET(portnum - 1,
1032 0, qp->qp_is_special);
1033 } else {
1034 return (IBT_HCA_PORT_INVALID);
1037 /* Check for valid PKey index and fill it in */
1038 pkeyindx = rc->rc_path.cep_pkey_ix;
1039 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1040 qpc->pri_addr_path.pkey_indx = pkeyindx;
1041 } else {
1042 return (IBT_PKEY_IX_ILLEGAL);
1045 } else if (qp->qp_serv_type == HERMON_QP_UC) {
1046 uc = &info_p->qp_transport.uc;
1049 * Set the RDMA (recv) enable/disable flags. Note: RDMA Read
1050 * and Atomic are ignored by default.
1052 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
1054 /* Check for valid port number and fill it in */
1055 portnum = uc->uc_path.cep_hca_port_num;
1056 if (hermon_portnum_is_valid(state, portnum)) {
1057 qp->qp_portnum = portnum - 1;
1058 qpc->pri_addr_path.sched_q =
1059 HERMON_QP_SCHEDQ_GET(portnum - 1,
1060 0, qp->qp_is_special);
1061 } else {
1062 return (IBT_HCA_PORT_INVALID);
1065 /* Check for valid PKey index and fill it in */
1066 pkeyindx = uc->uc_path.cep_pkey_ix;
1067 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1068 qpc->pri_addr_path.pkey_indx = pkeyindx;
1069 } else {
1070 return (IBT_PKEY_IX_ILLEGAL);
1073 } else {
1075 * Invalid QP transport type. If we got here then it's a
1076 * warning of a probably serious problem. So print a message
1077 * and return failure
1079 HERMON_WARNING(state, "unknown QP transport type in rst2init");
1080 return (ibc_get_ci_failure(0));
1084 * Post the RST2INIT_QP command to the Hermon firmware
1086 * We do a HERMON_NOSLEEP here because we are still holding the
1087 * "qp_lock". If we got raised to interrupt level by priority
1088 * inversion, we do not want to block in this routine waiting for
1089 * success.
1091 status = hermon_cmn_qp_cmd_post(state, RST2INIT_QP, qpc, qp->qp_qpnum,
1092 0, HERMON_CMD_NOSLEEP_SPIN);
1093 if (status != HERMON_CMD_SUCCESS) {
1094 cmn_err(CE_NOTE, "hermon%d: RST2INIT_QP command failed: %08x\n",
1095 state->hs_instance, status);
1096 if (status == HERMON_CMD_INVALID_STATUS) {
1097 hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_SRV_LOST);
1099 return (ibc_get_ci_failure(0));
1102 return (DDI_SUCCESS);
1107 * hermon_qp_init2init()
1108 * Context: Can be called from interrupt or base context.
1110 static int
1111 hermon_qp_init2init(hermon_state_t *state, hermon_qphdl_t qp,
1112 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p)
1114 hermon_hw_qpc_t *qpc;
1115 ibt_qp_rc_attr_t *rc;
1116 ibt_qp_ud_attr_t *ud;
1117 ibt_qp_uc_attr_t *uc;
1118 uint_t portnum, pkeyindx;
1119 uint32_t opmask = 0;
1120 int status;
1122 ASSERT(MUTEX_HELD(&qp->qp_lock));
1125 * Grab the temporary QPC entry from QP software state
1127 qpc = &qp->qpc;
1130 * Since there are no common fields to be filled in for this command,
1131 * we begin with the QPC fields which are specific to transport type.
1133 if (qp->qp_type == IBT_UD_RQP) {
1134 ud = &info_p->qp_transport.ud;
1137 * If we are attempting to modify the port for this QP, then
1138 * check for valid port number and fill it in. Also set the
1139 * appropriate flag in the "opmask" parameter.
1142 * set port is not supported in init2init - however, in init2rtr it will
1143 * take the entire qpc, including the embedded sched_q in the path
1144 * structure - so, we can just skip setting the opmask for it explicitly
1145 * and allow it to be set later on
1147 if (flags & IBT_CEP_SET_PORT) {
1148 portnum = ud->ud_port;
1149 if (hermon_portnum_is_valid(state, portnum)) {
1150 qp->qp_portnum = portnum - 1; /* save it away */
1151 qpc->pri_addr_path.sched_q =
1152 HERMON_QP_SCHEDQ_GET(portnum - 1,
1153 0, qp->qp_is_special);
1154 } else {
1155 return (IBT_HCA_PORT_INVALID);
1160 * If we are attempting to modify the PKey index for this QP,
1161 * then check for valid PKey index and fill it in. Also set
1162 * the appropriate flag in the "opmask" parameter.
1164 if (flags & IBT_CEP_SET_PKEY_IX) {
1165 pkeyindx = ud->ud_pkey_ix;
1166 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1167 qpc->pri_addr_path.pkey_indx = pkeyindx;
1168 opmask |= HERMON_CMD_OP_PKEYINDX;
1169 qp->qp_pkeyindx = pkeyindx;
1170 } else {
1171 return (IBT_PKEY_IX_ILLEGAL);
1176 * If we are attempting to modify the QKey for this QP, then
1177 * fill it in and set the appropriate flag in the "opmask"
1178 * parameter.
1180 if (flags & IBT_CEP_SET_QKEY) {
1181 qpc->qkey = ud->ud_qkey;
1182 opmask |= HERMON_CMD_OP_QKEY;
1185 } else if (qp->qp_serv_type == HERMON_QP_RC) {
1186 rc = &info_p->qp_transport.rc;
1189 * If we are attempting to modify the port for this QP, then
1190 * check for valid port number and fill it in. Also set the
1191 * appropriate flag in the "opmask" parameter.
1193 if (flags & IBT_CEP_SET_PORT) {
1194 portnum = rc->rc_path.cep_hca_port_num;
1195 if (hermon_portnum_is_valid(state, portnum)) {
1196 qp->qp_portnum = portnum - 1;
1197 qpc->pri_addr_path.sched_q =
1198 HERMON_QP_SCHEDQ_GET(portnum - 1,
1199 0, qp->qp_is_special);
1200 } else {
1201 return (IBT_HCA_PORT_INVALID);
1207 * If we are attempting to modify the PKey index for this QP,
1208 * then check for valid PKey index and fill it in. Also set
1209 * the appropriate flag in the "opmask" parameter.
1211 if (flags & IBT_CEP_SET_PKEY_IX) {
1212 pkeyindx = rc->rc_path.cep_pkey_ix;
1213 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1214 qpc->pri_addr_path.pkey_indx = pkeyindx;
1215 opmask |= HERMON_CMD_OP_PKEYINDX;
1216 } else {
1217 return (IBT_PKEY_IX_ILLEGAL);
1222 * Check if any of the flags indicate a change in the RDMA
1223 * (recv) enable/disable flags and set the appropriate flag in
1224 * the "opmask" parameter
1226 opmask |= hermon_check_rdma_enable_flags(flags, info_p, qpc);
1228 } else if (qp->qp_serv_type == HERMON_QP_UC) {
1229 uc = &info_p->qp_transport.uc;
1232 * If we are attempting to modify the port for this QP, then
1233 * check for valid port number and fill it in. Also set the
1234 * appropriate flag in the "opmask" parameter.
1236 if (flags & IBT_CEP_SET_PORT) {
1237 portnum = uc->uc_path.cep_hca_port_num;
1238 if (hermon_portnum_is_valid(state, portnum)) {
1239 qp->qp_portnum = portnum - 1;
1240 qpc->pri_addr_path.sched_q =
1241 HERMON_QP_SCHEDQ_GET(portnum - 1,
1242 0, qp->qp_is_special);
1243 } else {
1244 return (IBT_HCA_PORT_INVALID);
1246 /* port# cannot be set in this transition - defer to init2rtr */
1250 * If we are attempting to modify the PKey index for this QP,
1251 * then check for valid PKey index and fill it in. Also set
1252 * the appropriate flag in the "opmask" parameter.
1254 if (flags & IBT_CEP_SET_PKEY_IX) {
1255 pkeyindx = uc->uc_path.cep_pkey_ix;
1256 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1257 qpc->pri_addr_path.pkey_indx = pkeyindx;
1258 opmask |= HERMON_CMD_OP_PKEYINDX;
1259 } else {
1260 return (IBT_PKEY_IX_ILLEGAL);
1265 * Check if any of the flags indicate a change in the RDMA
1266 * Write (recv) enable/disable and set the appropriate flag
1267 * in the "opmask" parameter. Note: RDMA Read and Atomic are
1268 * not valid for UC transport.
1270 if (flags & IBT_CEP_SET_RDMA_W) {
1271 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
1272 opmask |= HERMON_CMD_OP_RWE;
1274 } else {
1276 * Invalid QP transport type. If we got here then it's a
1277 * warning of a probably serious problem. So print a message
1278 * and return failure
1280 HERMON_WARNING(state, "unknown QP transport type in init2init");
1281 return (ibc_get_ci_failure(0));
1285 * Post the INIT2INIT_QP command to the Hermon firmware
1287 * We do a HERMON_NOSLEEP here because we are still holding the
1288 * "qp_lock". If we got raised to interrupt level by priority
1289 * inversion, we do not want to block in this routine waiting for
1290 * success.
1292 status = hermon_cmn_qp_cmd_post(state, INIT2INIT_QP, qpc, qp->qp_qpnum,
1293 opmask, HERMON_CMD_NOSLEEP_SPIN);
1294 if (status != HERMON_CMD_SUCCESS) {
1295 if (status != HERMON_CMD_BAD_QP_STATE) {
1296 cmn_err(CE_NOTE, "hermon%d: INIT2INIT_QP command "
1297 "failed: %08x\n", state->hs_instance, status);
1298 if (status == HERMON_CMD_INVALID_STATUS) {
1299 hermon_fm_ereport(state, HCA_SYS_ERR,
1300 HCA_ERR_SRV_LOST);
1302 return (ibc_get_ci_failure(0));
1303 } else {
1304 return (IBT_QP_STATE_INVALID);
1308 return (DDI_SUCCESS);
1313 * hermon_qp_init2rtr()
1314 * Context: Can be called from interrupt or base context.
1316 static int
1317 hermon_qp_init2rtr(hermon_state_t *state, hermon_qphdl_t qp,
1318 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p)
1320 hermon_hw_qpc_t *qpc;
1321 ibt_qp_rc_attr_t *rc;
1322 ibt_qp_ud_attr_t *ud;
1323 ibt_qp_uc_attr_t *uc;
1324 hermon_hw_addr_path_t *qpc_path;
1325 ibt_adds_vect_t *adds_vect;
1326 uint_t portnum, pkeyindx, rra_max;
1327 uint_t mtu;
1328 uint32_t opmask = 0;
1329 int status;
1331 ASSERT(MUTEX_HELD(&qp->qp_lock));
1334 * Grab the temporary QPC entry from QP software state
1336 qpc = &qp->qpc;
1339 * Since there are few common fields to be filled in for this command,
1340 * we just do the QPC fields that are specific to transport type.
1342 if (qp->qp_type == IBT_UD_RQP) {
1343 ud = &info_p->qp_transport.ud;
1346 * If this UD QP is also a "special QP" (QP0 or QP1), then
1347 * the MTU is 256 bytes. However, Hermon checks the QPC
1348 * MTU settings rather than just the port MTU, so we will
1349 * set it to maximum size for all UD.
1351 qpc->mtu = HERMON_MAX_MTU;
1352 if (qp->qp_uses_lso)
1353 qpc->msg_max = state->hs_devlim.log_max_gso_sz;
1354 else
1355 qpc->msg_max = HERMON_QP_LOG_MAX_MSGSZ;
1358 * Save away the MTU value. This is used in future sqd2sqd
1359 * transitions, as the MTU must remain the same in future
1360 * changes.
1362 qp->qp_save_mtu = qpc->mtu;
1365 * If we are attempting to modify the PKey index for this QP,
1366 * then check for valid PKey index and fill it in. Also set
1367 * the appropriate flag in the "opmask" parameter.
1369 if (flags & IBT_CEP_SET_PKEY_IX) {
1370 pkeyindx = ud->ud_pkey_ix;
1371 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1372 qpc->pri_addr_path.pkey_indx = pkeyindx;
1373 opmask |= HERMON_CMD_OP_PKEYINDX;
1374 qp->qp_pkeyindx = pkeyindx;
1375 } else {
1376 return (IBT_PKEY_IX_ILLEGAL);
1381 * If we are attempting to modify the QKey for this QP, then
1382 * fill it in and set the appropriate flag in the "opmask"
1383 * parameter.
1385 if (flags & IBT_CEP_SET_QKEY) {
1386 qpc->qkey = ud->ud_qkey;
1387 opmask |= HERMON_CMD_OP_QKEY;
1390 } else if (qp->qp_serv_type == HERMON_QP_RC) {
1391 rc = &info_p->qp_transport.rc;
1392 qpc_path = &qpc->pri_addr_path;
1393 adds_vect = &rc->rc_path.cep_adds_vect;
1396 * Set the common primary address path fields
1398 status = hermon_set_addr_path(state, adds_vect, qpc_path,
1399 HERMON_ADDRPATH_QP);
1400 if (status != DDI_SUCCESS) {
1401 return (status);
1403 /* set the primary port number/sched_q */
1404 portnum = qp->qp_portnum + 1;
1405 if (hermon_portnum_is_valid(state, portnum)) {
1406 qpc->pri_addr_path.sched_q =
1407 HERMON_QP_SCHEDQ_GET(qp->qp_portnum,
1408 adds_vect->av_srvl, qp->qp_is_special);
1409 } else {
1410 return (IBT_HCA_PORT_INVALID);
1414 * The following values are apparently "required" here (as
1415 * they are part of the IBA-defined "Remote Node Address
1416 * Vector"). However, they are also going to be "required"
1417 * later - at RTR2RTS_QP time. Not sure why. But we set
1418 * them here anyway.
1420 qpc->rnr_retry = rc->rc_rnr_retry_cnt;
1421 qpc->retry_cnt = rc->rc_retry_cnt;
1422 qpc_path->ack_timeout = rc->rc_path.cep_timeout;
1425 * Setup the destination QP, recv PSN, MTU, max msg size,etc.
1426 * Note max message size is defined to be the maximum IB
1427 * allowed message size (which is 2^31 bytes). Also max
1428 * MTU is defined by HCA port properties.
1430 qpc->rem_qpn = rc->rc_dst_qpn;
1431 qpc->next_rcv_psn = rc->rc_rq_psn;
1432 qpc->msg_max = HERMON_QP_LOG_MAX_MSGSZ;
1433 qpc->ric = 0;
1434 mtu = rc->rc_path_mtu;
1436 if (hermon_qp_validate_mtu(state, mtu) != DDI_SUCCESS) {
1437 return (IBT_HCA_PORT_MTU_EXCEEDED);
1439 qpc->mtu = mtu;
1442 * Save away the MTU value. This is used in future sqd2sqd
1443 * transitions, as the MTU must remain the same in future
1444 * changes.
1446 qp->qp_save_mtu = qpc->mtu;
1449 * Though it is a "required" parameter, "min_rnr_nak" is
1450 * optionally specifiable in Hermon. So we force the
1451 * optional flag here.
1453 qpc->min_rnr_nak = rc->rc_min_rnr_nak;
1454 opmask |= HERMON_CMD_OP_MINRNRNAK;
1457 * Check that the number of specified "incoming RDMA resources"
1458 * is valid. And if it is, then setup the "rra_max
1460 if (hermon_qp_validate_resp_rsrc(state, rc, &rra_max) !=
1461 DDI_SUCCESS) {
1462 return (IBT_INVALID_PARAM);
1464 qpc->rra_max = rra_max;
1466 /* don't need to set up ra_buff_indx, implicit for hermon */
1469 * If we are attempting to modify the PKey index for this QP,
1470 * then check for valid PKey index and fill it in. Also set
1471 * the appropriate flag in the "opmask" parameter.
1473 if (flags & IBT_CEP_SET_PKEY_IX) {
1474 pkeyindx = rc->rc_path.cep_pkey_ix;
1475 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1476 qpc->pri_addr_path.pkey_indx = pkeyindx;
1477 opmask |= HERMON_CMD_OP_PKEYINDX;
1478 } else {
1479 return (IBT_PKEY_IX_ILLEGAL);
1484 * Check if any of the flags indicate a change in the RDMA
1485 * (recv) enable/disable flags and set the appropriate flag in
1486 * the "opmask" parameter
1488 opmask |= hermon_check_rdma_enable_flags(flags, info_p, qpc);
1491 * Check for optional alternate path and fill in the
1492 * appropriate QPC fields if one is specified
1494 if (flags & IBT_CEP_SET_ALT_PATH) {
1495 qpc_path = &qpc->alt_addr_path;
1496 adds_vect = &rc->rc_alt_path.cep_adds_vect;
1498 /* Set the common alternate address path fields */
1499 status = hermon_set_addr_path(state, adds_vect,
1500 qpc_path, HERMON_ADDRPATH_QP);
1501 if (status != DDI_SUCCESS) {
1502 return (status);
1504 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
1508 * Check for valid alternate path port number and fill
1509 * it in
1511 portnum = rc->rc_alt_path.cep_hca_port_num;
1512 if (hermon_portnum_is_valid(state, portnum)) {
1513 qp->qp_portnum_alt = portnum - 1;
1514 qpc->alt_addr_path.sched_q =
1515 HERMON_QP_SCHEDQ_GET(portnum - 1,
1516 adds_vect->av_srvl, qp->qp_is_special);
1517 } else {
1518 return (IBT_HCA_PORT_INVALID);
1521 * Check for valid alternate path PKey index and fill
1522 * it in
1524 pkeyindx = rc->rc_alt_path.cep_pkey_ix;
1525 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1526 qpc->alt_addr_path.pkey_indx = pkeyindx;
1527 } else {
1528 return (IBT_PKEY_IX_ILLEGAL);
1530 opmask |= HERMON_CMD_OP_ALT_PATH;
1533 } else if (qp->qp_serv_type == HERMON_QP_UC) {
1534 uc = &info_p->qp_transport.uc;
1535 qpc_path = &qpc->pri_addr_path;
1536 adds_vect = &uc->uc_path.cep_adds_vect;
1539 * Set the common primary address path fields
1541 status = hermon_set_addr_path(state, adds_vect, qpc_path,
1542 HERMON_ADDRPATH_QP);
1543 if (status != DDI_SUCCESS) {
1544 return (status);
1547 /* set the primary port num/schedq */
1548 portnum = qp->qp_portnum + 1;
1549 if (hermon_portnum_is_valid(state, portnum)) {
1550 qpc->pri_addr_path.sched_q =
1551 HERMON_QP_SCHEDQ_GET(qp->qp_portnum,
1552 adds_vect->av_srvl, qp->qp_is_special);
1553 } else {
1554 return (IBT_HCA_PORT_INVALID);
1558 * Setup the destination QP, recv PSN, MTU, max msg size,etc.
1559 * Note max message size is defined to be the maximum IB
1560 * allowed message size (which is 2^31 bytes). Also max
1561 * MTU is defined by HCA port properties.
1563 qpc->rem_qpn = uc->uc_dst_qpn;
1564 qpc->next_rcv_psn = uc->uc_rq_psn;
1565 qpc->msg_max = HERMON_QP_LOG_MAX_MSGSZ;
1566 mtu = uc->uc_path_mtu;
1567 if (hermon_qp_validate_mtu(state, mtu) != DDI_SUCCESS) {
1568 return (IBT_HCA_PORT_MTU_EXCEEDED);
1570 qpc->mtu = mtu;
1573 * Save away the MTU value. This is used in future sqd2sqd
1574 * transitions, as the MTU must remain the same in future
1575 * changes.
1577 qp->qp_save_mtu = qpc->mtu;
1580 * If we are attempting to modify the PKey index for this QP,
1581 * then check for valid PKey index and fill it in. Also set
1582 * the appropriate flag in the "opmask" parameter.
1584 if (flags & IBT_CEP_SET_PKEY_IX) {
1585 pkeyindx = uc->uc_path.cep_pkey_ix;
1586 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1587 qpc->pri_addr_path.pkey_indx = pkeyindx;
1588 opmask |= HERMON_CMD_OP_PKEYINDX;
1589 } else {
1590 return (IBT_PKEY_IX_ILLEGAL);
1595 * Check if any of the flags indicate a change in the RDMA
1596 * Write (recv) enable/disable and set the appropriate flag
1597 * in the "opmask" parameter. Note: RDMA Read and Atomic are
1598 * not valid for UC transport.
1600 if (flags & IBT_CEP_SET_RDMA_W) {
1601 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
1602 opmask |= HERMON_CMD_OP_RWE;
1606 * Check for optional alternate path and fill in the
1607 * appropriate QPC fields if one is specified
1609 if (flags & IBT_CEP_SET_ALT_PATH) {
1610 qpc_path = &qpc->alt_addr_path;
1611 adds_vect = &uc->uc_alt_path.cep_adds_vect;
1613 /* Set the common alternate address path fields */
1614 status = hermon_set_addr_path(state, adds_vect,
1615 qpc_path, HERMON_ADDRPATH_QP);
1616 if (status != DDI_SUCCESS) {
1617 return (status);
1620 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
1623 * Check for valid alternate path port number and fill
1624 * it in
1626 portnum = uc->uc_alt_path.cep_hca_port_num;
1627 if (hermon_portnum_is_valid(state, portnum)) {
1628 qp->qp_portnum_alt = portnum - 1;
1629 qpc->alt_addr_path.sched_q =
1630 HERMON_QP_SCHEDQ_GET(portnum - 1,
1631 adds_vect->av_srvl, qp->qp_is_special);
1632 } else {
1633 return (IBT_HCA_PORT_INVALID);
1637 * Check for valid alternate path PKey index and fill
1638 * it in
1640 pkeyindx = uc->uc_alt_path.cep_pkey_ix;
1641 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1642 qpc->alt_addr_path.pkey_indx = pkeyindx;
1643 } else {
1644 return (IBT_PKEY_IX_ILLEGAL);
1646 opmask |= HERMON_CMD_OP_ALT_PATH;
1648 } else {
1650 * Invalid QP transport type. If we got here then it's a
1651 * warning of a probably serious problem. So print a message
1652 * and return failure
1654 HERMON_WARNING(state, "unknown QP transport type in init2rtr");
1655 return (ibc_get_ci_failure(0));
1659 * Post the INIT2RTR_QP command to the Hermon firmware
1661 * We do a HERMON_NOSLEEP here because we are still holding the
1662 * "qp_lock". If we got raised to interrupt level by priority
1663 * inversion, we do not want to block in this routine waiting for
1664 * success.
1666 status = hermon_cmn_qp_cmd_post(state, INIT2RTR_QP, qpc, qp->qp_qpnum,
1667 opmask, HERMON_CMD_NOSLEEP_SPIN);
1668 if (status != HERMON_CMD_SUCCESS) {
1669 if (status != HERMON_CMD_BAD_QP_STATE) {
1670 cmn_err(CE_NOTE, "hermon%d: INIT2RTR_QP command "
1671 "failed: %08x\n", state->hs_instance, status);
1672 if (status == HERMON_CMD_INVALID_STATUS) {
1673 hermon_fm_ereport(state, HCA_SYS_ERR,
1674 HCA_ERR_SRV_LOST);
1676 return (ibc_get_ci_failure(0));
1677 } else {
1678 return (IBT_QP_STATE_INVALID);
1682 return (DDI_SUCCESS);
1687 * hermon_qp_rtr2rts()
1688 * Context: Can be called from interrupt or base context.
1690 static int
1691 hermon_qp_rtr2rts(hermon_state_t *state, hermon_qphdl_t qp,
1692 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p)
1694 hermon_hw_qpc_t *qpc;
1695 ibt_qp_rc_attr_t *rc;
1696 ibt_qp_ud_attr_t *ud;
1697 ibt_qp_uc_attr_t *uc;
1698 hermon_hw_addr_path_t *qpc_path;
1699 ibt_adds_vect_t *adds_vect;
1700 uint_t portnum, pkeyindx, sra_max;
1701 uint32_t opmask = 0;
1702 int status;
1704 ASSERT(MUTEX_HELD(&qp->qp_lock));
1707 * Grab the temporary QPC entry from QP software state
1709 qpc = &qp->qpc;
1712 * Now fill in the QPC fields which are specific to transport type
1714 if (qp->qp_type == IBT_UD_RQP) {
1715 ud = &info_p->qp_transport.ud;
1717 /* Set the send PSN */
1718 qpc->next_snd_psn = ud->ud_sq_psn;
1721 * If we are attempting to modify the QKey for this QP, then
1722 * fill it in and set the appropriate flag in the "opmask"
1723 * parameter.
1725 if (flags & IBT_CEP_SET_QKEY) {
1726 qpc->qkey = ud->ud_qkey;
1727 opmask |= HERMON_CMD_OP_QKEY;
1730 } else if (qp->qp_serv_type == HERMON_QP_RC) {
1731 rc = &info_p->qp_transport.rc;
1732 qpc_path = &qpc->pri_addr_path;
1735 * Setup the send PSN, ACK timeout, and retry counts
1737 qpc->next_snd_psn = rc->rc_sq_psn;
1738 qpc_path->ack_timeout = rc->rc_path.cep_timeout;
1739 qpc->rnr_retry = rc->rc_rnr_retry_cnt;
1740 /* in qpc now, not path */
1741 qpc->retry_cnt = rc->rc_retry_cnt;
1744 * Set "ack_req_freq" based on the configuration variable
1746 qpc->ack_req_freq = state->hs_cfg_profile->cp_ackreq_freq;
1749 * Check that the number of specified "outgoing RDMA resources"
1750 * is valid. And if it is, then setup the "sra_max"
1751 * appropriately
1753 if (hermon_qp_validate_init_depth(state, rc, &sra_max) !=
1754 DDI_SUCCESS) {
1755 return (IBT_INVALID_PARAM);
1757 qpc->sra_max = sra_max;
1761 * Check if any of the flags indicate a change in the RDMA
1762 * (recv) enable/disable flags and set the appropriate flag in
1763 * the "opmask" parameter
1765 opmask |= hermon_check_rdma_enable_flags(flags, info_p, qpc);
1768 * If we are attempting to modify the path migration state for
1769 * this QP, then check for valid state and fill it in. Also
1770 * set the appropriate flag in the "opmask" parameter.
1772 if (flags & IBT_CEP_SET_MIG) {
1773 if (rc->rc_mig_state == IBT_STATE_MIGRATED) {
1774 qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
1775 } else if (rc->rc_mig_state == IBT_STATE_REARMED) {
1776 qpc->pm_state = HERMON_QP_PMSTATE_REARM;
1777 } else {
1778 return (IBT_QP_APM_STATE_INVALID);
1780 opmask |= HERMON_CMD_OP_PM_STATE;
1784 * If we are attempting to modify the "Minimum RNR NAK" value
1785 * for this QP, then fill it in and set the appropriate flag
1786 * in the "opmask" parameter.
1788 if (flags & IBT_CEP_SET_MIN_RNR_NAK) {
1789 qpc->min_rnr_nak = rc->rc_min_rnr_nak;
1790 opmask |= HERMON_CMD_OP_MINRNRNAK;
1794 * Check for optional alternate path and fill in the
1795 * appropriate QPC fields if one is specified
1797 if (flags & IBT_CEP_SET_ALT_PATH) {
1798 qpc_path = &qpc->alt_addr_path;
1799 adds_vect = &rc->rc_alt_path.cep_adds_vect;
1801 /* Set the common alternate address path fields */
1802 status = hermon_set_addr_path(state, adds_vect,
1803 qpc_path, HERMON_ADDRPATH_QP);
1804 if (status != DDI_SUCCESS) {
1805 return (status);
1808 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
1811 * Check for valid alternate path port number and fill
1812 * it in
1814 portnum = rc->rc_alt_path.cep_hca_port_num;
1815 if (hermon_portnum_is_valid(state, portnum)) {
1816 qp->qp_portnum_alt = portnum - 1;
1817 qpc->alt_addr_path.sched_q =
1818 HERMON_QP_SCHEDQ_GET(portnum - 1,
1819 adds_vect->av_srvl, qp->qp_is_special);
1820 } else {
1821 return (IBT_HCA_PORT_INVALID);
1825 * Check for valid alternate path PKey index and fill
1826 * it in
1828 pkeyindx = rc->rc_alt_path.cep_pkey_ix;
1829 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1830 qpc->alt_addr_path.pkey_indx = pkeyindx;
1831 } else {
1832 return (IBT_PKEY_IX_ILLEGAL);
1834 opmask |= HERMON_CMD_OP_ALT_PATH;
1837 } else if (qp->qp_serv_type == HERMON_QP_UC) {
1838 uc = &info_p->qp_transport.uc;
1840 /* Set the send PSN */
1841 qpc->next_snd_psn = uc->uc_sq_psn;
1844 * Configure the QP to allow (sending of) all types of allowable
1845 * UC traffic (i.e. RDMA Write).
1850 * Check if any of the flags indicate a change in the RDMA
1851 * Write (recv) enable/disable and set the appropriate flag
1852 * in the "opmask" parameter. Note: RDMA Read and Atomic are
1853 * not valid for UC transport.
1855 if (flags & IBT_CEP_SET_RDMA_W) {
1856 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
1857 opmask |= HERMON_CMD_OP_RWE;
1861 * If we are attempting to modify the path migration state for
1862 * this QP, then check for valid state and fill it in. Also
1863 * set the appropriate flag in the "opmask" parameter.
1865 if (flags & IBT_CEP_SET_MIG) {
1866 if (uc->uc_mig_state == IBT_STATE_MIGRATED) {
1867 qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
1868 } else if (uc->uc_mig_state == IBT_STATE_REARMED) {
1869 qpc->pm_state = HERMON_QP_PMSTATE_REARM;
1870 } else {
1871 return (IBT_QP_APM_STATE_INVALID);
1873 opmask |= HERMON_CMD_OP_PM_STATE;
1877 * Check for optional alternate path and fill in the
1878 * appropriate QPC fields if one is specified
1880 if (flags & IBT_CEP_SET_ALT_PATH) {
1881 qpc_path = &qpc->alt_addr_path;
1882 adds_vect = &uc->uc_alt_path.cep_adds_vect;
1884 /* Set the common alternate address path fields */
1885 status = hermon_set_addr_path(state, adds_vect,
1886 qpc_path, HERMON_ADDRPATH_QP);
1887 if (status != DDI_SUCCESS) {
1888 return (status);
1890 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
1893 * Check for valid alternate path port number and fill
1894 * it in
1896 portnum = uc->uc_alt_path.cep_hca_port_num;
1897 if (hermon_portnum_is_valid(state, portnum)) {
1898 qpc->alt_addr_path.sched_q =
1899 HERMON_QP_SCHEDQ_GET(portnum - 1,
1900 adds_vect->av_srvl, qp->qp_is_special);
1901 } else {
1902 return (IBT_HCA_PORT_INVALID);
1906 * Check for valid alternate path PKey index and fill
1907 * it in
1909 pkeyindx = uc->uc_alt_path.cep_pkey_ix;
1910 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1911 qpc->alt_addr_path.pkey_indx = pkeyindx;
1912 } else {
1913 return (IBT_PKEY_IX_ILLEGAL);
1915 opmask |= HERMON_CMD_OP_ALT_PATH;
1917 } else {
1919 * Invalid QP transport type. If we got here then it's a
1920 * warning of a probably serious problem. So print a message
1921 * and return failure
1923 HERMON_WARNING(state, "unknown QP transport type in rtr2rts");
1924 return (ibc_get_ci_failure(0));
1928 * Post the RTR2RTS_QP command to the Hermon firmware
1930 * We do a HERMON_NOSLEEP here because we are still holding the
1931 * "qp_lock". If we got raised to interrupt level by priority
1932 * inversion, we do not want to block in this routine waiting for
1933 * success.
1935 status = hermon_cmn_qp_cmd_post(state, RTR2RTS_QP, qpc, qp->qp_qpnum,
1936 opmask, HERMON_CMD_NOSLEEP_SPIN);
1937 if (status != HERMON_CMD_SUCCESS) {
1938 if (status != HERMON_CMD_BAD_QP_STATE) {
1939 cmn_err(CE_NOTE, "hermon%d: RTR2RTS_QP command failed: "
1940 "%08x\n", state->hs_instance, status);
1941 if (status == HERMON_CMD_INVALID_STATUS) {
1942 hermon_fm_ereport(state, HCA_SYS_ERR,
1943 HCA_ERR_SRV_LOST);
1945 return (ibc_get_ci_failure(0));
1946 } else {
1947 return (IBT_QP_STATE_INVALID);
1951 return (DDI_SUCCESS);
1956 * hermon_qp_rts2rts()
1957 * Context: Can be called from interrupt or base context.
1959 static int
1960 hermon_qp_rts2rts(hermon_state_t *state, hermon_qphdl_t qp,
1961 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p)
1963 hermon_hw_qpc_t *qpc;
1964 ibt_qp_rc_attr_t *rc;
1965 ibt_qp_ud_attr_t *ud;
1966 ibt_qp_uc_attr_t *uc;
1967 hermon_hw_addr_path_t *qpc_path;
1968 ibt_adds_vect_t *adds_vect;
1969 uint_t portnum, pkeyindx;
1970 uint32_t opmask = 0;
1971 int status;
1973 ASSERT(MUTEX_HELD(&qp->qp_lock));
1976 * Grab the temporary QPC entry from QP software state
1979 qpc = &qp->qpc;
1982 * Since there are no common fields to be filled in for this command,
1983 * we begin with the QPC fields which are specific to transport type.
1985 if (qp->qp_type == IBT_UD_RQP) {
1986 ud = &info_p->qp_transport.ud;
1989 * If we are attempting to modify the QKey for this QP, then
1990 * fill it in and set the appropriate flag in the "opmask"
1991 * parameter.
1993 if (flags & IBT_CEP_SET_QKEY) {
1994 qpc->qkey = ud->ud_qkey;
1995 opmask |= HERMON_CMD_OP_QKEY;
1998 } else if (qp->qp_serv_type == HERMON_QP_RC) {
1999 rc = &info_p->qp_transport.rc;
2002 * Check if any of the flags indicate a change in the RDMA
2003 * (recv) enable/disable flags and set the appropriate flag in
2004 * the "opmask" parameter
2006 opmask |= hermon_check_rdma_enable_flags(flags, info_p, qpc);
2009 * If we are attempting to modify the path migration state for
2010 * this QP, then check for valid state and fill it in. Also
2011 * set the appropriate flag in the "opmask" parameter.
2013 if (flags & IBT_CEP_SET_MIG) {
2014 if (rc->rc_mig_state == IBT_STATE_MIGRATED) {
2015 qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
2016 } else if (rc->rc_mig_state == IBT_STATE_REARMED) {
2017 qpc->pm_state = HERMON_QP_PMSTATE_REARM;
2018 } else {
2019 return (IBT_QP_APM_STATE_INVALID);
2021 opmask |= HERMON_CMD_OP_PM_STATE;
2025 * If we are attempting to modify the "Minimum RNR NAK" value
2026 * for this QP, then fill it in and set the appropriate flag
2027 * in the "opmask" parameter.
2029 if (flags & IBT_CEP_SET_MIN_RNR_NAK) {
2030 qpc->min_rnr_nak = rc->rc_min_rnr_nak;
2031 opmask |= HERMON_CMD_OP_MINRNRNAK;
2035 * Check for optional alternate path and fill in the
2036 * appropriate QPC fields if one is specified
2038 if (flags & IBT_CEP_SET_ALT_PATH) {
2039 qpc_path = &qpc->alt_addr_path;
2040 adds_vect = &rc->rc_alt_path.cep_adds_vect;
2042 /* Set the common alternate address path fields */
2043 status = hermon_set_addr_path(state, adds_vect,
2044 qpc_path, HERMON_ADDRPATH_QP);
2045 if (status != DDI_SUCCESS) {
2046 return (status);
2048 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
2051 * Check for valid alternate path port number and fill
2052 * it in
2054 portnum = rc->rc_alt_path.cep_hca_port_num;
2055 if (hermon_portnum_is_valid(state, portnum)) {
2056 qp->qp_portnum_alt = portnum - 1;
2057 qpc->alt_addr_path.sched_q =
2058 HERMON_QP_SCHEDQ_GET(portnum - 1,
2059 adds_vect->av_srvl, qp->qp_is_special);
2060 } else {
2061 return (IBT_HCA_PORT_INVALID);
2065 * Check for valid alternate path PKey index and fill
2066 * it in
2068 pkeyindx = rc->rc_alt_path.cep_pkey_ix;
2069 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
2070 qpc->alt_addr_path.pkey_indx = pkeyindx;
2071 } else {
2072 return (IBT_PKEY_IX_ILLEGAL);
2074 opmask |= HERMON_CMD_OP_ALT_PATH;
2077 } else if (qp->qp_serv_type == HERMON_QP_UC) {
2078 uc = &info_p->qp_transport.uc;
2081 * Check if any of the flags indicate a change in the RDMA
2082 * Write (recv) enable/disable and set the appropriate flag
2083 * in the "opmask" parameter. Note: RDMA Read and Atomic are
2084 * not valid for UC transport.
2086 if (flags & IBT_CEP_SET_RDMA_W) {
2087 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
2088 opmask |= HERMON_CMD_OP_RWE;
2092 * If we are attempting to modify the path migration state for
2093 * this QP, then check for valid state and fill it in. Also
2094 * set the appropriate flag in the "opmask" parameter.
2096 if (flags & IBT_CEP_SET_MIG) {
2097 if (uc->uc_mig_state == IBT_STATE_MIGRATED) {
2098 qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
2099 } else if (uc->uc_mig_state == IBT_STATE_REARMED) {
2100 qpc->pm_state = HERMON_QP_PMSTATE_REARM;
2101 } else {
2102 return (IBT_QP_APM_STATE_INVALID);
2104 opmask |= HERMON_CMD_OP_PM_STATE;
2108 * Check for optional alternate path and fill in the
2109 * appropriate QPC fields if one is specified
2111 if (flags & IBT_CEP_SET_ALT_PATH) {
2112 qpc_path = &qpc->alt_addr_path;
2113 adds_vect = &uc->uc_alt_path.cep_adds_vect;
2115 /* Set the common alternate address path fields */
2116 status = hermon_set_addr_path(state, adds_vect,
2117 qpc_path, HERMON_ADDRPATH_QP);
2118 if (status != DDI_SUCCESS) {
2119 return (status);
2123 * Check for valid alternate path port number and fill
2124 * it in
2126 portnum = uc->uc_alt_path.cep_hca_port_num;
2127 if (hermon_portnum_is_valid(state, portnum)) {
2128 qp->qp_portnum_alt = portnum - 1;
2129 qpc->alt_addr_path.sched_q =
2130 HERMON_QP_SCHEDQ_GET(portnum - 1,
2131 adds_vect->av_srvl, qp->qp_is_special);
2132 } else {
2133 return (IBT_HCA_PORT_INVALID);
2137 * Check for valid alternate path PKey index and fill
2138 * it in
2140 pkeyindx = uc->uc_alt_path.cep_pkey_ix;
2141 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
2142 qpc->alt_addr_path.pkey_indx = pkeyindx;
2143 } else {
2144 return (IBT_PKEY_IX_ILLEGAL);
2146 opmask |= HERMON_CMD_OP_ALT_PATH;
2148 } else {
2150 * Invalid QP transport type. If we got here then it's a
2151 * warning of a probably serious problem. So print a message
2152 * and return failure
2154 HERMON_WARNING(state, "unknown QP transport type in rts2rts");
2155 return (ibc_get_ci_failure(0));
2159 * Post the RTS2RTS_QP command to the Hermon firmware
2161 * We do a HERMON_NOSLEEP here because we are still holding the
2162 * "qp_lock". If we got raised to interrupt level by priority
2163 * inversion, we do not want to block in this routine waiting for
2164 * success.
2166 status = hermon_cmn_qp_cmd_post(state, RTS2RTS_QP, qpc, qp->qp_qpnum,
2167 opmask, HERMON_CMD_NOSLEEP_SPIN);
2168 if (status != HERMON_CMD_SUCCESS) {
2169 if (status != HERMON_CMD_BAD_QP_STATE) {
2170 cmn_err(CE_NOTE, "hermon%d: RTS2RTS_QP command failed: "
2171 "%08x\n", state->hs_instance, status);
2172 if (status == HERMON_CMD_INVALID_STATUS) {
2173 hermon_fm_ereport(state, HCA_SYS_ERR,
2174 HCA_ERR_SRV_LOST);
2176 return (ibc_get_ci_failure(0));
2177 } else {
2178 return (IBT_QP_STATE_INVALID);
2182 return (DDI_SUCCESS);
2186 #ifdef HERMON_NOTNOW
2188 * hermon_qp_rts2sqd()
2189 * Context: Can be called from interrupt or base context.
2191 static int
2192 hermon_qp_rts2sqd(hermon_state_t *state, hermon_qphdl_t qp,
2193 ibt_cep_modify_flags_t flags)
2195 int status;
2197 ASSERT(MUTEX_HELD(&qp->qp_lock));
2200 * Set a flag to indicate whether or not the consumer is interested
2201 * in receiving the SQ drained event. Since we are going to always
2202 * request hardware generation of the SQD event, we use the value in
2203 * "qp_forward_sqd_event" to determine whether or not to pass the event
2204 * to the IBTF or to silently consume it.
2206 qp->qp_forward_sqd_event = (flags & IBT_CEP_SET_SQD_EVENT) ? 1 : 0;
2209 * Post the RTS2SQD_QP command to the Hermon firmware
2211 * We do a HERMON_NOSLEEP here because we are still holding the
2212 * "qp_lock". If we got raised to interrupt level by priority
2213 * inversion, we do not want to block in this routine waiting for
2214 * success.
2216 status = hermon_cmn_qp_cmd_post(state, RTS2SQD_QP, NULL, qp->qp_qpnum,
2217 0, HERMON_CMD_NOSLEEP_SPIN);
2218 if (status != HERMON_CMD_SUCCESS) {
2219 if (status != HERMON_CMD_BAD_QP_STATE) {
2220 cmn_err(CE_NOTE, "hermon%d: RTS2SQD_QP command failed: "
2221 "%08x\n", state->hs_instance, status);
2222 if (status == HERMON_CMD_INVALID_STATUS) {
2223 hermon_fm_ereport(state, HCA_SYS_ERR,
2224 HCA_ERR_SRV_LOST);
2226 return (ibc_get_ci_failure(0));
2227 } else {
2228 return (IBT_QP_STATE_INVALID);
2233 * Mark the current QP state as "SQ Draining". This allows us to
2234 * distinguish between the two underlying states in SQD. (see QueryQP()
2235 * code in hermon_qp.c)
2237 qp->qp_sqd_still_draining = 1;
2239 return (DDI_SUCCESS);
2241 #endif
2245 * hermon_qp_sqd2rts()
2246 * Context: Can be called from interrupt or base context.
2248 static int
2249 hermon_qp_sqd2rts(hermon_state_t *state, hermon_qphdl_t qp,
2250 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p)
2252 hermon_hw_qpc_t *qpc;
2253 ibt_qp_rc_attr_t *rc;
2254 ibt_qp_ud_attr_t *ud;
2255 ibt_qp_uc_attr_t *uc;
2256 hermon_hw_addr_path_t *qpc_path;
2257 ibt_adds_vect_t *adds_vect;
2258 uint_t portnum, pkeyindx;
2259 uint_t rra_max, sra_max;
2260 uint32_t opmask = 0;
2261 int status;
2263 ASSERT(MUTEX_HELD(&qp->qp_lock));
2266 * Grab the temporary QPC entry from QP software state
2268 qpc = &qp->qpc;
2271 * Fill in the common fields in the QPC
2275 * Now fill in the QPC fields which are specific to transport type
2277 if (qp->qp_type == IBT_UD_RQP) {
2278 ud = &info_p->qp_transport.ud;
2281 * If we are attempting to modify the port for this QP, then
2282 * check for valid port number and fill it in. Also set the
2283 * appropriate flag in the "opmask" parameter.
2285 if (flags & IBT_CEP_SET_PORT) {
2286 portnum = ud->ud_port;
2287 if (hermon_portnum_is_valid(state, portnum)) {
2288 qp->qp_portnum = portnum - 1;
2289 qpc->pri_addr_path.sched_q =
2290 HERMON_QP_SCHEDQ_GET(portnum - 1,
2291 0, qp->qp_is_special);
2292 } else {
2293 return (IBT_HCA_PORT_INVALID);
2295 opmask |= HERMON_CMD_OP_PRIM_PORT;
2299 * If we are attempting to modify the PKey index for this QP,
2300 * then check for valid PKey index and fill it in. Also set
2301 * the appropriate flag in the "opmask" parameter.
2303 if (flags & IBT_CEP_SET_PKEY_IX) {
2304 pkeyindx = ud->ud_pkey_ix;
2305 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
2306 qpc->pri_addr_path.pkey_indx = pkeyindx;
2307 opmask |= HERMON_CMD_OP_PKEYINDX;
2308 qp->qp_pkeyindx = pkeyindx;
2309 } else {
2310 return (IBT_PKEY_IX_ILLEGAL);
2315 * If we are attempting to modify the QKey for this QP, then
2316 * fill it in and set the appropriate flag in the "opmask"
2317 * parameter.
2319 if (flags & IBT_CEP_SET_QKEY) {
2320 qpc->qkey = ud->ud_qkey;
2321 opmask |= HERMON_CMD_OP_QKEY;
2324 } else if (qp->qp_serv_type == HERMON_QP_RC) {
2325 rc = &info_p->qp_transport.rc;
2328 * Check if any of the flags indicate a change in the RDMA
2329 * (recv) enable/disable flags and set the appropriate flag in
2330 * the "opmask" parameter
2332 opmask |= hermon_check_rdma_enable_flags(flags, info_p, qpc);
2334 qpc->retry_cnt = rc->rc_retry_cnt;
2337 * If we are attempting to modify the path migration state for
2338 * this QP, then check for valid state and fill it in. Also
2339 * set the appropriate flag in the "opmask" parameter.
2341 if (flags & IBT_CEP_SET_MIG) {
2342 if (rc->rc_mig_state == IBT_STATE_MIGRATED) {
2343 qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
2344 } else if (rc->rc_mig_state == IBT_STATE_REARMED) {
2345 qpc->pm_state = HERMON_QP_PMSTATE_REARM;
2346 } else {
2347 return (IBT_QP_APM_STATE_INVALID);
2349 opmask |= HERMON_CMD_OP_PM_STATE;
2353 * Check for optional alternate path and fill in the
2354 * appropriate QPC fields if one is specified
2356 if (flags & IBT_CEP_SET_ALT_PATH) {
2357 qpc_path = &qpc->alt_addr_path;
2358 adds_vect = &rc->rc_alt_path.cep_adds_vect;
2360 /* Set the common alternate address path fields */
2361 status = hermon_set_addr_path(state, adds_vect,
2362 qpc_path, HERMON_ADDRPATH_QP);
2363 if (status != DDI_SUCCESS) {
2364 return (status);
2366 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
2368 * Check for valid alternate path port number and fill
2369 * it in
2371 portnum = rc->rc_alt_path.cep_hca_port_num;
2372 if (hermon_portnum_is_valid(state, portnum)) {
2373 qp->qp_portnum_alt = portnum - 1;
2374 qpc->alt_addr_path.sched_q =
2375 HERMON_QP_SCHEDQ_GET(portnum - 1,
2376 adds_vect->av_srvl, qp->qp_is_special);
2377 } else {
2378 return (IBT_HCA_PORT_INVALID);
2382 * Check for valid alternate path PKey index and fill
2383 * it in
2385 pkeyindx = rc->rc_alt_path.cep_pkey_ix;
2386 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
2387 qpc->alt_addr_path.pkey_indx = pkeyindx;
2388 } else {
2389 return (IBT_PKEY_IX_ILLEGAL);
2391 opmask |= HERMON_CMD_OP_ALT_PATH;
2395 * If we are attempting to modify the number of "outgoing
2396 * RDMA resources" for this QP, then check for valid value and
2397 * fill it in. Also set the appropriate flag in the "opmask"
2398 * parameter.
2400 if (flags & IBT_CEP_SET_RDMARA_OUT) {
2401 if (hermon_qp_validate_init_depth(state, rc,
2402 &sra_max) != DDI_SUCCESS) {
2403 return (IBT_INVALID_PARAM);
2405 qpc->sra_max = sra_max;
2406 opmask |= HERMON_CMD_OP_SRA_SET;
2410 * If we are attempting to modify the number of "incoming
2411 * RDMA resources" for this QP, then check for valid value and
2412 * update the "rra_max" and "ra_buf_index" fields in the QPC to
2413 * point to the pre-allocated RDB resources (in DDR). Also set
2414 * the appropriate flag in the "opmask" parameter.
2416 if (flags & IBT_CEP_SET_RDMARA_IN) {
2417 if (hermon_qp_validate_resp_rsrc(state, rc,
2418 &rra_max) != DDI_SUCCESS) {
2419 return (IBT_INVALID_PARAM);
2421 qpc->rra_max = rra_max;
2422 opmask |= HERMON_CMD_OP_RRA_SET;
2427 * If we are attempting to modify the "Minimum RNR NAK" value
2428 * for this QP, then fill it in and set the appropriate flag
2429 * in the "opmask" parameter.
2431 if (flags & IBT_CEP_SET_MIN_RNR_NAK) {
2432 qpc->min_rnr_nak = rc->rc_min_rnr_nak;
2433 opmask |= HERMON_CMD_OP_MINRNRNAK;
2436 } else if (qp->qp_serv_type == HERMON_QP_UC) {
2437 uc = &info_p->qp_transport.uc;
2440 * Check if any of the flags indicate a change in the RDMA
2441 * Write (recv) enable/disable and set the appropriate flag
2442 * in the "opmask" parameter. Note: RDMA Read and Atomic are
2443 * not valid for UC transport.
2445 if (flags & IBT_CEP_SET_RDMA_W) {
2446 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
2447 opmask |= HERMON_CMD_OP_RWE;
2451 * If we are attempting to modify the path migration state for
2452 * this QP, then check for valid state and fill it in. Also
2453 * set the appropriate flag in the "opmask" parameter.
2455 if (flags & IBT_CEP_SET_MIG) {
2456 if (uc->uc_mig_state == IBT_STATE_MIGRATED) {
2457 qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
2458 } else if (uc->uc_mig_state == IBT_STATE_REARMED) {
2459 qpc->pm_state = HERMON_QP_PMSTATE_REARM;
2460 } else {
2461 return (IBT_QP_APM_STATE_INVALID);
2463 opmask |= HERMON_CMD_OP_PM_STATE;
2467 * Check for optional alternate path and fill in the
2468 * appropriate QPC fields if one is specified
2470 if (flags & IBT_CEP_SET_ALT_PATH) {
2471 qpc_path = &qpc->alt_addr_path;
2472 adds_vect = &uc->uc_alt_path.cep_adds_vect;
2474 /* Set the common alternate address path fields */
2475 status = hermon_set_addr_path(state, adds_vect,
2476 qpc_path, HERMON_ADDRPATH_QP);
2477 if (status != DDI_SUCCESS) {
2478 return (status);
2482 * Check for valid alternate path port number and fill
2483 * it in
2485 portnum = uc->uc_alt_path.cep_hca_port_num;
2486 if (hermon_portnum_is_valid(state, portnum)) {
2487 qp->qp_portnum_alt = portnum - 1;
2488 qpc->alt_addr_path.sched_q =
2489 HERMON_QP_SCHEDQ_GET(portnum - 1,
2490 adds_vect->av_srvl, qp->qp_is_special);
2491 } else {
2492 return (IBT_HCA_PORT_INVALID);
2496 * Check for valid alternate path PKey index and fill
2497 * it in
2499 pkeyindx = uc->uc_alt_path.cep_pkey_ix;
2500 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
2501 qpc->alt_addr_path.pkey_indx = pkeyindx;
2502 } else {
2503 return (IBT_PKEY_IX_ILLEGAL);
2505 opmask |= HERMON_CMD_OP_ALT_PATH;
2507 } else {
2509 * Invalid QP transport type. If we got here then it's a
2510 * warning of a probably serious problem. So print a message
2511 * and return failure
2513 HERMON_WARNING(state, "unknown QP transport type in sqd2rts");
2514 return (ibc_get_ci_failure(0));
2518 * Post the SQD2RTS_QP command to the Hermon firmware
2520 * We do a HERMON_NOSLEEP here because we are still holding the
2521 * "qp_lock". If we got raised to interrupt level by priority
2522 * inversion, we do not want to block in this routine waiting for
2523 * success.
2525 status = hermon_cmn_qp_cmd_post(state, SQD2RTS_QP, qpc, qp->qp_qpnum,
2526 opmask, HERMON_CMD_NOSLEEP_SPIN);
2527 if (status != HERMON_CMD_SUCCESS) {
2528 if (status != HERMON_CMD_BAD_QP_STATE) {
2529 cmn_err(CE_NOTE, "hermon%d: SQD2RTS_QP command failed: "
2530 "%08x\n", state->hs_instance, status);
2531 if (status == HERMON_CMD_INVALID_STATUS) {
2532 hermon_fm_ereport(state, HCA_SYS_ERR,
2533 HCA_ERR_SRV_LOST);
2535 return (ibc_get_ci_failure(0));
2536 } else {
2537 return (IBT_QP_STATE_INVALID);
2541 return (DDI_SUCCESS);
2546 * hermon_qp_sqd2sqd()
2547 * Context: Can be called from interrupt or base context.
2549 static int
2550 hermon_qp_sqd2sqd(hermon_state_t *state, hermon_qphdl_t qp,
2551 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p)
2553 hermon_hw_qpc_t *qpc;
2554 ibt_qp_rc_attr_t *rc;
2555 ibt_qp_ud_attr_t *ud;
2556 ibt_qp_uc_attr_t *uc;
2557 hermon_hw_addr_path_t *qpc_path;
2558 ibt_adds_vect_t *adds_vect;
2559 uint_t portnum, pkeyindx;
2560 uint_t rra_max, sra_max;
2561 uint32_t opmask = 0;
2562 int status;
2564 ASSERT(MUTEX_HELD(&qp->qp_lock));
2567 * Grab the temporary QPC entry from QP software state
2569 qpc = &qp->qpc;
2572 * Fill in the common fields in the QPC
2576 * Now fill in the QPC fields which are specific to transport type
2578 if (qp->qp_type == IBT_UD_RQP) {
2579 ud = &info_p->qp_transport.ud;
2582 * If we are attempting to modify the port for this QP, then
2583 * check for valid port number and fill it in. Also set the
2584 * appropriate flag in the "opmask" parameter.
2586 if (flags & IBT_CEP_SET_PORT) {
2587 portnum = ud->ud_port;
2588 if (hermon_portnum_is_valid(state, portnum)) {
2589 qp->qp_portnum = portnum - 1;
2590 qpc->pri_addr_path.sched_q =
2591 HERMON_QP_SCHEDQ_GET(portnum - 1,
2592 0, qp->qp_is_special);
2593 } else {
2594 return (IBT_HCA_PORT_INVALID);
2596 opmask |= HERMON_CMD_OP_SCHEDQUEUE;
2600 * If we are attempting to modify the PKey index for this QP,
2601 * then check for valid PKey index and fill it in. Also set
2602 * the appropriate flag in the "opmask" parameter.
2604 if (flags & IBT_CEP_SET_PKEY_IX) {
2605 pkeyindx = ud->ud_pkey_ix;
2606 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
2607 qpc->pri_addr_path.pkey_indx = pkeyindx;
2608 opmask |= HERMON_CMD_OP_PKEYINDX;
2609 qp->qp_pkeyindx = pkeyindx;
2610 } else {
2611 return (IBT_PKEY_IX_ILLEGAL);
2616 * If we are attempting to modify the QKey for this QP, then
2617 * fill it in and set the appropriate flag in the "opmask"
2618 * parameter.
2620 if (flags & IBT_CEP_SET_QKEY) {
2621 qpc->qkey = ud->ud_qkey;
2622 opmask |= HERMON_CMD_OP_QKEY;
2625 } else if (qp->qp_serv_type == HERMON_QP_RC) {
2626 rc = &info_p->qp_transport.rc;
2629 * Check if any of the flags indicate a change in the RDMA
2630 * (recv) enable/disable flags and set the appropriate flag in
2631 * the "opmask" parameter
2633 opmask |= hermon_check_rdma_enable_flags(flags, info_p, qpc);
2636 * Check for optional primary path and fill in the
2637 * appropriate QPC fields if one is specified
2639 if (flags & IBT_CEP_SET_ADDS_VECT) {
2640 qpc_path = &qpc->pri_addr_path;
2641 adds_vect = &rc->rc_path.cep_adds_vect;
2643 /* Set the common primary address path fields */
2644 status = hermon_set_addr_path(state, adds_vect,
2645 qpc_path, HERMON_ADDRPATH_QP);
2646 if (status != DDI_SUCCESS) {
2647 return (status);
2649 qpc->rnr_retry = rc->rc_rnr_retry_cnt;
2650 qpc_path->ack_timeout = rc->rc_path.cep_timeout;
2651 qpc->retry_cnt = rc->rc_retry_cnt;
2653 portnum = qp->qp_portnum + 1;
2654 if (hermon_portnum_is_valid(state, portnum)) {
2655 qpc->pri_addr_path.sched_q =
2656 HERMON_QP_SCHEDQ_GET(qp->qp_portnum,
2657 adds_vect->av_srvl, qp->qp_is_special);
2658 } else {
2659 return (IBT_HCA_PORT_INVALID);
2663 * MTU changes as part of sqd2sqd are not allowed.
2664 * Simply keep the same MTU value here, stored in the
2665 * qphdl from init2rtr time.
2667 qpc->mtu = qp->qp_save_mtu;
2669 opmask |= (HERMON_CMD_OP_PRIM_PATH |
2670 HERMON_CMD_OP_RETRYCNT | HERMON_CMD_OP_ACKTIMEOUT |
2671 HERMON_CMD_OP_PRIM_RNRRETRY);
2675 * If we are attempting to modify the path migration state for
2676 * this QP, then check for valid state and fill it in. Also
2677 * set the appropriate flag in the "opmask" parameter.
2679 if (flags & IBT_CEP_SET_MIG) {
2680 if (rc->rc_mig_state == IBT_STATE_MIGRATED) {
2681 qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
2682 } else if (rc->rc_mig_state == IBT_STATE_REARMED) {
2683 qpc->pm_state = HERMON_QP_PMSTATE_REARM;
2684 } else {
2685 return (IBT_QP_APM_STATE_INVALID);
2687 opmask |= HERMON_CMD_OP_PM_STATE;
2691 * If we are attempting to modify the PKey index for this QP,
2692 * then check for valid PKey index and fill it in. Also set
2693 * the appropriate flag in the "opmask" parameter.
2695 if (flags & IBT_CEP_SET_PKEY_IX) {
2696 pkeyindx = rc->rc_path.cep_pkey_ix;
2697 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
2698 qpc->pri_addr_path.pkey_indx = pkeyindx;
2699 opmask |= HERMON_CMD_OP_PKEYINDX;
2700 } else {
2701 return (IBT_PKEY_IX_ILLEGAL);
2706 * If we are attempting to modify the port for this QP, then
2707 * check for valid port number and fill it in. Also set the
2708 * appropriate flag in the "opmask" parameter.
2710 if (flags & IBT_CEP_SET_PORT) {
2711 portnum = rc->rc_path.cep_hca_port_num;
2712 if (hermon_portnum_is_valid(state, portnum)) {
2713 qp->qp_portnum = portnum - 1;
2714 qpc->pri_addr_path.sched_q =
2715 HERMON_QP_SCHEDQ_GET(portnum - 1,
2716 adds_vect->av_srvl, qp->qp_is_special);
2717 } else {
2718 return (IBT_HCA_PORT_INVALID);
2720 opmask |= HERMON_CMD_OP_SCHEDQUEUE;
2724 * Check for optional alternate path and fill in the
2725 * appropriate QPC fields if one is specified
2727 if (flags & IBT_CEP_SET_ALT_PATH) {
2728 qpc_path = &qpc->alt_addr_path;
2729 adds_vect = &rc->rc_alt_path.cep_adds_vect;
2731 /* Set the common alternate address path fields */
2732 status = hermon_set_addr_path(state, adds_vect,
2733 qpc_path, HERMON_ADDRPATH_QP);
2734 if (status != DDI_SUCCESS) {
2735 return (status);
2737 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
2740 * Check for valid alternate path port number and fill
2741 * it in
2743 portnum = rc->rc_alt_path.cep_hca_port_num;
2744 if (hermon_portnum_is_valid(state, portnum)) {
2745 qp->qp_portnum_alt = portnum - 1;
2746 qpc->alt_addr_path.sched_q =
2747 HERMON_QP_SCHEDQ_GET(portnum - 1,
2748 adds_vect->av_srvl, qp->qp_is_special);
2749 } else {
2750 return (IBT_HCA_PORT_INVALID);
2754 * Check for valid alternate path PKey index and fill
2755 * it in
2757 pkeyindx = rc->rc_alt_path.cep_pkey_ix;
2758 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
2759 qpc->alt_addr_path.pkey_indx = pkeyindx;
2760 } else {
2761 return (IBT_PKEY_IX_ILLEGAL);
2763 opmask |= HERMON_CMD_OP_ALT_PATH;
2767 * If we are attempting to modify the number of "outgoing
2768 * RDMA resources" for this QP, then check for valid value and
2769 * fill it in. Also set the appropriate flag in the "opmask"
2770 * parameter.
2772 if (flags & IBT_CEP_SET_RDMARA_OUT) {
2773 if (hermon_qp_validate_init_depth(state, rc,
2774 &sra_max) != DDI_SUCCESS) {
2775 return (IBT_INVALID_PARAM);
2777 qpc->sra_max = sra_max;
2778 opmask |= HERMON_CMD_OP_SRA_SET;
2782 * If we are attempting to modify the number of "incoming
2783 * RDMA resources" for this QP, then check for valid value and
2784 * update the "rra_max" and "ra_buf_index" fields in the QPC to
2785 * point to the pre-allocated RDB resources (in DDR). Also set
2786 * the appropriate flag in the "opmask" parameter.
2788 if (flags & IBT_CEP_SET_RDMARA_IN) {
2789 if (hermon_qp_validate_resp_rsrc(state, rc,
2790 &rra_max) != DDI_SUCCESS) {
2791 return (IBT_INVALID_PARAM);
2793 qpc->rra_max = rra_max;
2794 opmask |= HERMON_CMD_OP_RRA_SET;
2798 * If we are attempting to modify the "Local Ack Timeout" value
2799 * for this QP, then fill it in and set the appropriate flag in
2800 * the "opmask" parameter.
2802 if (flags & IBT_CEP_SET_TIMEOUT) {
2803 qpc_path = &qpc->pri_addr_path;
2804 qpc_path->ack_timeout = rc->rc_path.cep_timeout;
2805 opmask |= HERMON_CMD_OP_ACKTIMEOUT;
2809 * If we are attempting to modify the "Retry Count" for this QP,
2810 * then fill it in and set the appropriate flag in the "opmask"
2811 * parameter.
2813 if (flags & IBT_CEP_SET_RETRY) {
2814 qpc->retry_cnt = rc->rc_retry_cnt;
2815 opmask |= HERMON_CMD_OP_PRIM_RNRRETRY;
2819 * If we are attempting to modify the "RNR Retry Count" for this
2820 * QP, then fill it in and set the appropriate flag in the
2821 * "opmask" parameter.
2823 if (flags & IBT_CEP_SET_RNR_NAK_RETRY) {
2824 qpc_path = &qpc->pri_addr_path;
2825 qpc->rnr_retry = rc->rc_rnr_retry_cnt;
2826 opmask |= HERMON_CMD_OP_RETRYCNT;
2830 * If we are attempting to modify the "Minimum RNR NAK" value
2831 * for this QP, then fill it in and set the appropriate flag
2832 * in the "opmask" parameter.
2834 if (flags & IBT_CEP_SET_MIN_RNR_NAK) {
2835 qpc->min_rnr_nak = rc->rc_min_rnr_nak;
2836 opmask |= HERMON_CMD_OP_MINRNRNAK;
2839 } else if (qp->qp_serv_type == HERMON_QP_UC) {
2840 uc = &info_p->qp_transport.uc;
2843 * Check if any of the flags indicate a change in the RDMA
2844 * Write (recv) enable/disable and set the appropriate flag
2845 * in the "opmask" parameter. Note: RDMA Read and Atomic are
2846 * not valid for UC transport.
2848 if (flags & IBT_CEP_SET_RDMA_W) {
2849 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
2850 opmask |= HERMON_CMD_OP_RWE;
2854 * Check for optional primary path and fill in the
2855 * appropriate QPC fields if one is specified
2857 if (flags & IBT_CEP_SET_ADDS_VECT) {
2858 qpc_path = &qpc->pri_addr_path;
2859 adds_vect = &uc->uc_path.cep_adds_vect;
2861 /* Set the common primary address path fields */
2862 status = hermon_set_addr_path(state, adds_vect,
2863 qpc_path, HERMON_ADDRPATH_QP);
2864 if (status != DDI_SUCCESS) {
2865 return (status);
2867 portnum = qp->qp_portnum + 1;
2868 if (hermon_portnum_is_valid(state, portnum)) {
2869 qpc->pri_addr_path.sched_q =
2870 HERMON_QP_SCHEDQ_GET(qp->qp_portnum,
2871 adds_vect->av_srvl, qp->qp_is_special);
2872 } else {
2873 return (IBT_HCA_PORT_INVALID);
2877 * MTU changes as part of sqd2sqd are not allowed.
2878 * Simply keep the same MTU value here, stored in the
2879 * qphdl from init2rtr time.
2881 qpc->mtu = qp->qp_save_mtu;
2883 opmask |= HERMON_CMD_OP_PRIM_PATH;
2887 * If we are attempting to modify the path migration state for
2888 * this QP, then check for valid state and fill it in. Also
2889 * set the appropriate flag in the "opmask" parameter.
2891 if (flags & IBT_CEP_SET_MIG) {
2892 if (uc->uc_mig_state == IBT_STATE_MIGRATED) {
2893 qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
2894 } else if (uc->uc_mig_state == IBT_STATE_REARMED) {
2895 qpc->pm_state = HERMON_QP_PMSTATE_REARM;
2896 } else {
2897 return (IBT_QP_APM_STATE_INVALID);
2899 opmask |= HERMON_CMD_OP_PM_STATE;
2903 * If we are attempting to modify the PKey index for this QP,
2904 * then check for valid PKey index and fill it in. Also set
2905 * the appropriate flag in the "opmask" parameter.
2907 if (flags & IBT_CEP_SET_PKEY_IX) {
2908 pkeyindx = uc->uc_path.cep_pkey_ix;
2909 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
2910 qpc->pri_addr_path.pkey_indx = pkeyindx;
2911 opmask |= HERMON_CMD_OP_PKEYINDX;
2912 } else {
2913 return (IBT_PKEY_IX_ILLEGAL);
2918 * Check for optional alternate path and fill in the
2919 * appropriate QPC fields if one is specified
2921 if (flags & IBT_CEP_SET_ALT_PATH) {
2922 qpc_path = &qpc->alt_addr_path;
2923 adds_vect = &uc->uc_alt_path.cep_adds_vect;
2925 /* Set the common alternate address path fields */
2926 status = hermon_set_addr_path(state, adds_vect,
2927 qpc_path, HERMON_ADDRPATH_QP);
2928 if (status != DDI_SUCCESS) {
2929 return (status);
2933 * Check for valid alternate path port number and fill
2934 * it in
2936 portnum = uc->uc_alt_path.cep_hca_port_num;
2937 if (hermon_portnum_is_valid(state, portnum)) {
2938 qp->qp_portnum_alt = portnum - 1;
2939 qpc->alt_addr_path.sched_q =
2940 HERMON_QP_SCHEDQ_GET(portnum - 1,
2941 adds_vect->av_srvl, qp->qp_is_special);
2942 } else {
2943 return (IBT_HCA_PORT_INVALID);
2947 * Check for valid alternate path PKey index and fill
2948 * it in
2950 pkeyindx = uc->uc_alt_path.cep_pkey_ix;
2951 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
2952 qpc->alt_addr_path.pkey_indx = pkeyindx;
2953 } else {
2954 return (IBT_PKEY_IX_ILLEGAL);
2956 opmask |= HERMON_CMD_OP_ALT_PATH;
2958 } else {
2960 * Invalid QP transport type. If we got here then it's a
2961 * warning of a probably serious problem. So print a message
2962 * and return failure
2964 HERMON_WARNING(state, "unknown QP transport type in sqd2sqd");
2965 return (ibc_get_ci_failure(0));
2969 * Post the SQD2SQD_QP command to the Hermon firmware
2971 * We do a HERMON_NOSLEEP here because we are still holding the
2972 * "qp_lock". If we got raised to interrupt level by priority
2973 * inversion, we do not want to block in this routine waiting for
2974 * success.
2976 status = hermon_cmn_qp_cmd_post(state, SQD2SQD_QP, qpc, qp->qp_qpnum,
2977 opmask, HERMON_CMD_NOSLEEP_SPIN);
2978 if (status != HERMON_CMD_SUCCESS) {
2979 if (status != HERMON_CMD_BAD_QP_STATE) {
2980 cmn_err(CE_NOTE, "hermon%d: SQD2SQD_QP command failed: "
2981 "%08x\n", state->hs_instance, status);
2982 if (status == HERMON_CMD_INVALID_STATUS) {
2983 hermon_fm_ereport(state, HCA_SYS_ERR,
2984 HCA_ERR_SRV_LOST);
2986 return (ibc_get_ci_failure(0));
2987 } else {
2988 return (IBT_QP_STATE_INVALID);
2992 return (DDI_SUCCESS);
2997 * hermon_qp_sqerr2rts()
2998 * Context: Can be called from interrupt or base context.
3000 static int
3001 hermon_qp_sqerr2rts(hermon_state_t *state, hermon_qphdl_t qp,
3002 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p)
3004 hermon_hw_qpc_t *qpc;
3005 ibt_qp_ud_attr_t *ud;
3006 uint32_t opmask = 0;
3007 int status;
3009 ASSERT(MUTEX_HELD(&qp->qp_lock));
3012 * Grab the temporary QPC entry from QP software state
3014 qpc = &qp->qpc;
3017 * Since there are no common fields to be filled in for this command,
3018 * we begin with the QPC fields which are specific to transport type.
3020 if (qp->qp_type == IBT_UD_RQP) {
3021 ud = &info_p->qp_transport.ud;
3024 * If we are attempting to modify the QKey for this QP, then
3025 * fill it in and set the appropriate flag in the "opmask"
3026 * parameter.
3028 if (flags & IBT_CEP_SET_QKEY) {
3029 qpc->qkey = ud->ud_qkey;
3030 opmask |= HERMON_CMD_OP_QKEY;
3033 } else if (qp->qp_serv_type == HERMON_QP_UC) {
3036 * Check if any of the flags indicate a change in the RDMA
3037 * Write (recv) enable/disable and set the appropriate flag
3038 * in the "opmask" parameter. Note: RDMA Read and Atomic are
3039 * not valid for UC transport.
3041 if (flags & IBT_CEP_SET_RDMA_W) {
3042 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
3043 opmask |= HERMON_CMD_OP_RWE;
3045 } else {
3047 * Invalid QP transport type. If we got here then it's a
3048 * warning of a probably serious problem. So print a message
3049 * and return failure
3051 HERMON_WARNING(state, "unknown QP transport type in sqerr2rts");
3052 return (ibc_get_ci_failure(0));
3056 * Post the SQERR2RTS_QP command to the Hermon firmware
3058 * We do a HERMON_NOSLEEP here because we are still holding the
3059 * "qp_lock". If we got raised to interrupt level by priority
3060 * inversion, we do not want to block in this routine waiting for
3061 * success.
3063 status = hermon_cmn_qp_cmd_post(state, SQERR2RTS_QP, qpc, qp->qp_qpnum,
3064 opmask, HERMON_CMD_NOSLEEP_SPIN);
3065 if (status != HERMON_CMD_SUCCESS) {
3066 if (status != HERMON_CMD_BAD_QP_STATE) {
3067 cmn_err(CE_NOTE, "hermon%d: SQERR2RTS_QP command "
3068 "failed: %08x\n", state->hs_instance, status);
3069 if (status == HERMON_CMD_INVALID_STATUS) {
3070 hermon_fm_ereport(state, HCA_SYS_ERR,
3071 HCA_ERR_SRV_LOST);
3073 return (ibc_get_ci_failure(0));
3074 } else {
3075 return (IBT_QP_STATE_INVALID);
3079 return (DDI_SUCCESS);
3084 * hermon_qp_to_error()
3085 * Context: Can be called from interrupt or base context.
3087 static int
3088 hermon_qp_to_error(hermon_state_t *state, hermon_qphdl_t qp)
3090 int status;
3092 ASSERT(MUTEX_HELD(&qp->qp_lock));
3095 * Post the TOERR_QP command to the Hermon firmware
3097 * We do a HERMON_NOSLEEP here because we are still holding the
3098 * "qp_lock". If we got raised to interrupt level by priority
3099 * inversion, we do not want to block in this routine waiting for
3100 * success.
3102 status = hermon_cmn_qp_cmd_post(state, TOERR_QP, NULL, qp->qp_qpnum,
3103 0, HERMON_CMD_NOSLEEP_SPIN);
3104 if (status != HERMON_CMD_SUCCESS) {
3105 cmn_err(CE_NOTE, "hermon%d: TOERR_QP command failed: %08x\n",
3106 state->hs_instance, status);
3107 if (status == HERMON_CMD_INVALID_STATUS) {
3108 hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_SRV_LOST);
3110 return (ibc_get_ci_failure(0));
3113 return (DDI_SUCCESS);
3118 * hermon_qp_to_reset()
3119 * Context: Can be called from interrupt or base context.
3122 hermon_qp_to_reset(hermon_state_t *state, hermon_qphdl_t qp)
3124 hermon_hw_qpc_t *qpc;
3125 int status;
3127 ASSERT(MUTEX_HELD(&qp->qp_lock));
3130 * Grab the temporary QPC entry from QP software state
3132 qpc = &qp->qpc;
3135 * Post the TORST_QP command to the Hermon firmware
3137 * We do a HERMON_NOSLEEP here because we are still holding the
3138 * "qp_lock". If we got raised to interrupt level by priority
3139 * inversion, we do not want to block in this routine waiting for
3140 * success.
3142 status = hermon_cmn_qp_cmd_post(state, TORST_QP, qpc, qp->qp_qpnum,
3143 0, HERMON_CMD_NOSLEEP_SPIN);
3144 if (status != HERMON_CMD_SUCCESS) {
3145 cmn_err(CE_NOTE, "hermon%d: TORST_QP command failed: %08x\n",
3146 state->hs_instance, status);
3147 if (status == HERMON_CMD_INVALID_STATUS) {
3148 hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_SRV_LOST);
3150 return (ibc_get_ci_failure(0));
3152 if (qp->qp_serv_type == HERMON_QP_FEXCH) {
3153 status = hermon_fcoib_fexch_mkey_fini(state, qp->qp_pdhdl,
3154 qp->qp_qpnum, HERMON_CMD_NOSLEEP_SPIN);
3155 if (status != DDI_SUCCESS)
3156 cmn_err(CE_NOTE, "hermon%d: fexch_mkey_fini failed "
3157 "%08x\n", state->hs_instance, status);
3159 return (DDI_SUCCESS);
3164 * hermon_qp_reset2err()
3165 * Context: Can be called from interrupt or base context.
3167 static int
3168 hermon_qp_reset2err(hermon_state_t *state, hermon_qphdl_t qp)
3170 hermon_hw_qpc_t *qpc;
3171 int status;
3172 uint32_t cqnmask;
3174 ASSERT(MUTEX_HELD(&qp->qp_lock));
3177 * In order to implement the transition from "Reset" directly to the
3178 * "Error" state, it is necessary to first give ownership of the QP
3179 * context to the Hermon hardware. This is accomplished by
3180 * transitioning the QP to "Init" as an intermediate step and then,
3181 * immediately transitioning to "Error".
3183 * When this function returns success, the QP context will be owned by
3184 * the Hermon hardware and will be in the "Error" state.
3188 * Grab the temporary QPC entry from QP software state
3190 qpc = &qp->qpc;
3193 * Fill in the common fields in the QPC
3195 if (qp->qp_is_special) {
3196 qpc->serv_type = HERMON_QP_MLX;
3197 } else {
3198 qpc->serv_type = qp->qp_serv_type;
3200 qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
3201 qpc->usr_page = qp->qp_uarpg;
3202 /* dbr is now an address, not an index */
3203 qpc->dbr_addrh = ((uint64_t)qp->qp_rq_pdbr >> 32);
3204 qpc->dbr_addrl = ((uint64_t)qp->qp_rq_pdbr & 0xFFFFFFFC) >> 2;
3205 qpc->pd = qp->qp_pdhdl->pd_pdnum;
3207 * HERMON:
3208 * qpc->wqe_baseaddr is replaced by LKey from the cMPT, and
3209 * page_offset, mtt_base_addr_h/l, and log2_page_size will
3210 * be used to map the WQE buffer
3211 * NOTE that the cMPT is created implicitly when the QP is
3212 * transitioned from reset to init
3214 qpc->log2_pgsz = qp->qp_mrhdl->mr_log2_pgsz;
3215 qpc->mtt_base_addrh = (qp->qp_mrhdl->mr_mttaddr) >> 32 & 0xFF;
3216 qpc->mtt_base_addrl = (qp->qp_mrhdl->mr_mttaddr) >> 3 & 0xFFFFFFFF;
3217 cqnmask = (1 << state->hs_cfg_profile->cp_log_num_cq) - 1;
3218 qpc->cqn_snd =
3219 (qp->qp_sq_cqhdl == NULL) ? 0 : qp->qp_sq_cqhdl->cq_cqnum & cqnmask;
3220 qpc->page_offs = qp->qp_wqinfo.qa_pgoffs >> 6;
3221 qpc->cqn_rcv =
3222 (qp->qp_rq_cqhdl == NULL) ? 0 : qp->qp_rq_cqhdl->cq_cqnum & cqnmask;
3224 qpc->sq_wqe_counter = 0;
3225 qpc->rq_wqe_counter = 0;
3226 qpc->log_sq_stride = qp->qp_sq_log_wqesz - 4;
3227 qpc->log_rq_stride = qp->qp_rq_log_wqesz - 4;
3228 qpc->log_sq_size = highbit(qp->qp_sq_bufsz) - 1;
3229 qpc->log_rq_size = highbit(qp->qp_rq_bufsz) - 1;
3230 qpc->srq_en = (qp->qp_alloc_flags & IBT_QP_USES_SRQ) != 0;
3231 qpc->sq_no_prefetch = qp->qp_no_prefetch;
3233 if (qp->qp_alloc_flags & IBT_QP_USES_SRQ) {
3234 qpc->srq_number = qp->qp_srqhdl->srq_srqnum;
3235 } else {
3236 qpc->srq_number = 0;
3239 qpc->fre = 0; /* default disable fast registration WR */
3240 qpc->rlky = 0; /* default disable reserved lkey */
3243 * Now fill in the QPC fields which are specific to transport type
3245 if (qp->qp_type == IBT_UD_RQP) {
3246 /* Set the UD parameters to an invalid default */
3247 qpc->qkey = 0;
3248 qpc->pri_addr_path.sched_q =
3249 HERMON_QP_SCHEDQ_GET(0, 0, qp->qp_is_special);
3250 qpc->pri_addr_path.pkey_indx = 0;
3252 } else if (qp->qp_serv_type == HERMON_QP_RC) {
3253 /* Set the RC parameters to invalid default */
3254 qpc->rre = 0;
3255 qpc->rwe = 0;
3256 qpc->rae = 0;
3257 qpc->alt_addr_path.sched_q =
3258 HERMON_QP_SCHEDQ_GET(0, 0, qp->qp_is_special);
3259 qpc->pri_addr_path.pkey_indx = 0;
3261 } else if (qp->qp_serv_type == HERMON_QP_UC) {
3262 /* Set the UC parameters to invalid default */
3263 qpc->rwe = 0;
3264 qpc->alt_addr_path.sched_q =
3265 HERMON_QP_SCHEDQ_GET(0, 0, qp->qp_is_special);
3266 qpc->pri_addr_path.pkey_indx = 0;
3268 } else {
3270 * Invalid QP transport type. If we got here then it's a
3271 * warning of a probably serious problem. So print a message
3272 * and return failure
3274 HERMON_WARNING(state, "unknown QP transport type in rst2err");
3275 return (ibc_get_ci_failure(0));
3279 * Post the RST2INIT_QP command to the Hermon firmware
3281 * We do a HERMON_NOSLEEP here because we are still holding the
3282 * "qp_lock". If we got raised to interrupt level by priority
3283 * inversion, we do not want to block in this routine waiting for
3284 * success.
3286 status = hermon_cmn_qp_cmd_post(state, RST2INIT_QP, qpc, qp->qp_qpnum,
3287 0, HERMON_CMD_NOSLEEP_SPIN);
3288 if (status != HERMON_CMD_SUCCESS) {
3289 cmn_err(CE_NOTE, "hermon%d: RST2INIT_QP command failed: %08x\n",
3290 state->hs_instance, status);
3291 if (status == HERMON_CMD_INVALID_STATUS) {
3292 hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_SRV_LOST);
3294 return (ibc_get_ci_failure(0));
3298 * Now post the TOERR_QP command to the Hermon firmware
3300 * We still do a HERMON_NOSLEEP here because we are still holding the
3301 * "qp_lock". Note: If this fails (which it really never should),
3302 * it indicates a serious problem in the HW or SW. We try to move
3303 * the QP back to the "Reset" state if possible and print a warning
3304 * message if not. In any case, we return an error here.
3306 status = hermon_cmn_qp_cmd_post(state, TOERR_QP, NULL, qp->qp_qpnum,
3307 0, HERMON_CMD_NOSLEEP_SPIN);
3308 if (status != HERMON_CMD_SUCCESS) {
3309 cmn_err(CE_NOTE, "hermon%d: TOERR_QP command failed: %08x\n",
3310 state->hs_instance, status);
3311 if (status == HERMON_CMD_INVALID_STATUS) {
3312 hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_SRV_LOST);
3314 if (hermon_qp_to_reset(state, qp) != DDI_SUCCESS) {
3315 HERMON_WARNING(state, "failed to reset QP context");
3317 return (ibc_get_ci_failure(0));
3320 return (DDI_SUCCESS);
3325 * hermon_check_rdma_enable_flags()
3326 * Context: Can be called from interrupt or base context.
3328 static uint_t
3329 hermon_check_rdma_enable_flags(ibt_cep_modify_flags_t flags,
3330 ibt_qp_info_t *info_p, hermon_hw_qpc_t *qpc)
3332 uint_t opmask = 0;
3334 if (flags & IBT_CEP_SET_RDMA_R) {
3335 qpc->rre = (info_p->qp_flags & IBT_CEP_RDMA_RD) ? 1 : 0;
3336 opmask |= HERMON_CMD_OP_RRE;
3339 if (flags & IBT_CEP_SET_RDMA_W) {
3340 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
3341 opmask |= HERMON_CMD_OP_RWE;
3344 if (flags & IBT_CEP_SET_ATOMIC) {
3345 qpc->rae = (info_p->qp_flags & IBT_CEP_ATOMIC) ? 1 : 0;
3346 opmask |= HERMON_CMD_OP_RAE;
3349 return (opmask);
3353 * hermon_qp_validate_resp_rsrc()
3354 * Context: Can be called from interrupt or base context.
3356 static int
3357 hermon_qp_validate_resp_rsrc(hermon_state_t *state, ibt_qp_rc_attr_t *rc,
3358 uint_t *rra_max)
3360 uint_t rdma_ra_in;
3362 rdma_ra_in = rc->rc_rdma_ra_in;
3365 * Check if number of responder resources is too large. Return an
3366 * error if it is
3368 if (rdma_ra_in > state->hs_cfg_profile->cp_hca_max_rdma_in_qp) {
3369 return (IBT_INVALID_PARAM);
3373 * If the number of responder resources is too small, round it up.
3374 * Then find the next highest power-of-2
3376 if (rdma_ra_in == 0) {
3377 rdma_ra_in = 1;
3379 if (ISP2(rdma_ra_in)) {
3380 *rra_max = highbit(rdma_ra_in) - 1;
3381 } else {
3382 *rra_max = highbit(rdma_ra_in);
3384 return (DDI_SUCCESS);
3389 * hermon_qp_validate_init_depth()
3390 * Context: Can be called from interrupt or base context.
3392 static int
3393 hermon_qp_validate_init_depth(hermon_state_t *state, ibt_qp_rc_attr_t *rc,
3394 uint_t *sra_max)
3396 uint_t rdma_ra_out;
3398 rdma_ra_out = rc->rc_rdma_ra_out;
3401 * Check if requested initiator depth is too large. Return an error
3402 * if it is
3404 if (rdma_ra_out > state->hs_cfg_profile->cp_hca_max_rdma_out_qp) {
3405 return (IBT_INVALID_PARAM);
3409 * If the requested initiator depth is too small, round it up.
3410 * Then find the next highest power-of-2
3412 if (rdma_ra_out == 0) {
3413 rdma_ra_out = 1;
3415 if (ISP2(rdma_ra_out)) {
3416 *sra_max = highbit(rdma_ra_out) - 1;
3417 } else {
3418 *sra_max = highbit(rdma_ra_out);
3420 return (DDI_SUCCESS);
3425 * hermon_qp_validate_mtu()
3426 * Context: Can be called from interrupt or base context.
3428 static int
3429 hermon_qp_validate_mtu(hermon_state_t *state, uint_t mtu)
3432 * Check for invalid MTU values (i.e. zero or any value larger than
3433 * the HCA's port maximum).
3435 if ((mtu == 0) || (mtu > state->hs_cfg_profile->cp_max_mtu)) {
3436 return (IBT_HCA_PORT_MTU_EXCEEDED);
3438 return (DDI_SUCCESS);