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]
23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
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,
36 #include <sys/sysmacros.h>
37 #include <sys/types.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
);
58 static int hermon_qp_rts2sqd(hermon_state_t
*state
, hermon_qphdl_t qp
,
59 ibt_cep_modify_flags_t flags
);
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
);
80 * Context: Can be called from interrupt or base context.
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
;
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
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
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
) {
147 cur_state
= HERMON_QP_RTR
; /* Ready to Receive */
150 cur_state
= HERMON_QP_RTS
; /* Ready to Send */
153 cur_state
= HERMON_QP_SQERR
; /* Send Queue Error */
156 cur_state
= HERMON_QP_SQD
; /* SQ Drained */
159 mutex_exit(&qp
->qp_lock
);
160 return (IBT_QP_STATE_INVALID
);
163 cur_state
= qp
->qp_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
177 if (flags
& ~okflags
) {
178 mutex_exit(&qp
->qp_lock
);
179 status
= IBT_QP_ATTR_RO
;
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
;
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
);
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
);
235 qp
->qp_state
= HERMON_QP_ERR
;
236 HERMON_SET_QP_POST_SEND_STATE(qp
, HERMON_QP_ERR
);
239 /* Invalid transition - return error */
240 mutex_exit(&qp
->qp_lock
);
241 status
= IBT_QP_STATE_INVALID
;
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
);
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
279 if (flags
& ~okflags
) {
280 mutex_exit(&qp
->qp_lock
);
281 status
= IBT_QP_ATTR_RO
;
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
;
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
);
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
);
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
);
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
342 status
= hermon_wrid_to_reset_handling(state
, qp
);
343 if (status
!= IBT_SUCCESS
) {
344 mutex_exit(&qp
->qp_lock
);
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
);
358 qp
->qp_state
= HERMON_QP_ERR
;
359 HERMON_SET_QP_POST_SEND_STATE(qp
, HERMON_QP_ERR
);
362 /* Invalid transition - return error */
363 mutex_exit(&qp
->qp_lock
);
364 status
= IBT_QP_STATE_INVALID
;
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
382 if (flags
& ~okflags
) {
383 mutex_exit(&qp
->qp_lock
);
384 status
= IBT_QP_ATTR_RO
;
389 * Verify state transition is to either "RTS", "Reset",
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
;
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
);
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
);
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
432 status
= hermon_wrid_to_reset_handling(state
, qp
);
433 if (status
!= IBT_SUCCESS
) {
434 mutex_exit(&qp
->qp_lock
);
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
);
448 qp
->qp_state
= HERMON_QP_ERR
;
449 HERMON_SET_QP_POST_SEND_STATE(qp
, HERMON_QP_ERR
);
452 /* Invalid transition - return error */
453 mutex_exit(&qp
->qp_lock
);
454 status
= IBT_QP_STATE_INVALID
;
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
470 if (flags
& ~okflags
) {
471 mutex_exit(&qp
->qp_lock
);
472 status
= IBT_QP_ATTR_RO
;
477 * Verify state transition is to either "RTS", "SQD", "Reset",
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
);
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
)) {
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
);
504 qp
->qp_state
= HERMON_QP_SQD
;
505 HERMON_SET_QP_POST_SEND_STATE(qp
, HERMON_QP_SQD
);
507 /* hack because of the lack of fw support for SQD */
508 mutex_exit(&qp
->qp_lock
);
509 status
= IBT_QP_STATE_INVALID
;
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
);
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
531 status
= hermon_wrid_to_reset_handling(state
, qp
);
532 if (status
!= IBT_SUCCESS
) {
533 mutex_exit(&qp
->qp_lock
);
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
);
547 qp
->qp_state
= HERMON_QP_ERR
;
548 HERMON_SET_QP_POST_SEND_STATE(qp
, HERMON_QP_ERR
);
551 /* Invalid transition - return error */
552 mutex_exit(&qp
->qp_lock
);
553 status
= IBT_QP_STATE_INVALID
;
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
567 if (flags
& ~okflags
) {
568 mutex_exit(&qp
->qp_lock
);
569 status
= IBT_QP_ATTR_RO
;
574 * Verify state transition is to either "RTS", "Reset", or
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
);
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
);
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
608 status
= hermon_wrid_to_reset_handling(state
, qp
);
609 if (status
!= IBT_SUCCESS
) {
610 mutex_exit(&qp
->qp_lock
);
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
);
624 qp
->qp_state
= HERMON_QP_ERR
;
625 HERMON_SET_QP_POST_SEND_STATE(qp
, HERMON_QP_ERR
);
628 /* Invalid transition - return error */
629 mutex_exit(&qp
->qp_lock
);
630 status
= IBT_QP_STATE_INVALID
;
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
649 if (flags
& ~okflags
) {
650 mutex_exit(&qp
->qp_lock
);
651 status
= IBT_QP_ATTR_RO
;
656 * Verify state transition is to either "SQD", "RTS", "Reset",
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
);
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
);
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
);
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
);
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
);
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
733 status
= hermon_wrid_to_reset_handling(state
, qp
);
734 if (status
!= IBT_SUCCESS
) {
735 mutex_exit(&qp
->qp_lock
);
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
);
749 qp
->qp_state
= HERMON_QP_ERR
;
750 HERMON_SET_QP_POST_SEND_STATE(qp
, HERMON_QP_ERR
);
753 /* Invalid transition - return error */
754 mutex_exit(&qp
->qp_lock
);
755 status
= IBT_QP_STATE_INVALID
;
762 * Verify state transition is to either "Reset" or back to
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
);
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
783 status
= hermon_wrid_to_reset_handling(state
, qp
);
784 if (status
!= IBT_SUCCESS
) {
785 mutex_exit(&qp
->qp_lock
);
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
);
802 /* Invalid transition - return error */
803 mutex_exit(&qp
->qp_lock
);
804 status
= IBT_QP_STATE_INVALID
;
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
815 mutex_exit(&qp
->qp_lock
);
816 HERMON_WARNING(state
, "unknown QP state in modify");
817 status
= IBT_QP_STATE_INVALID
;
821 mutex_exit(&qp
->qp_lock
);
822 return (DDI_SUCCESS
);
830 * hermon_qp_reset2init()
831 * Context: Can be called from interrupt or base context.
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
;
846 ASSERT(MUTEX_HELD(&qp
->qp_lock
));
849 * Grab the temporary QPC entry from QP software state
854 * Fill in the common fields in the QPC
857 if (qp
->qp_is_special
) {
858 qpc
->serv_type
= HERMON_QP_MLX
;
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;
876 (qp
->qp_sq_cqhdl
== NULL
) ? 0 : qp
->qp_sq_cqhdl
->cq_cqnum
& cqnmask
;
877 qpc
->page_offs
= qp
->qp_wqinfo
.qa_pgoffs
>> 6;
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;
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) &
898 qp_srq_en
= (qp
->qp_alloc_flags
& IBT_QP_USES_SRQ
) != 0;
899 qpc
->srq_en
= qp_srq_en
;
902 qpc
->srq_number
= qp
->qp_srqhdl
->srq_srqnum
;
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
;
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
;
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;
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
);
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
;
961 return (IBT_PKEY_IX_ILLEGAL
);
964 /* fill in the RSS fields */
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 */
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
)
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
)
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
);
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
;
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
);
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
;
1070 return (IBT_PKEY_IX_ILLEGAL
);
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
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.
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;
1122 ASSERT(MUTEX_HELD(&qp
->qp_lock
));
1125 * Grab the temporary QPC entry from QP software state
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
);
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
;
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"
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
);
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
;
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
);
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
;
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
;
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
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
,
1302 return (ibc_get_ci_failure(0));
1304 return (IBT_QP_STATE_INVALID
);
1308 return (DDI_SUCCESS
);
1313 * hermon_qp_init2rtr()
1314 * Context: Can be called from interrupt or base context.
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
;
1328 uint32_t opmask
= 0;
1331 ASSERT(MUTEX_HELD(&qp
->qp_lock
));
1334 * Grab the temporary QPC entry from QP software state
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
;
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
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
;
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"
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
) {
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
);
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
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
;
1434 mtu
= rc
->rc_path_mtu
;
1436 if (hermon_qp_validate_mtu(state
, mtu
) != DDI_SUCCESS
) {
1437 return (IBT_HCA_PORT_MTU_EXCEEDED
);
1442 * Save away the MTU value. This is used in future sqd2sqd
1443 * transitions, as the MTU must remain the same in future
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
) !=
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
;
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
) {
1504 qpc_path
->ack_timeout
= rc
->rc_alt_path
.cep_timeout
;
1508 * Check for valid alternate path port number and fill
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
);
1518 return (IBT_HCA_PORT_INVALID
);
1521 * Check for valid alternate path PKey index and fill
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
;
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
) {
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
);
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
);
1573 * Save away the MTU value. This is used in future sqd2sqd
1574 * transitions, as the MTU must remain the same in future
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
;
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
) {
1620 qpc_path
->ack_timeout
= rc
->rc_alt_path
.cep_timeout
;
1623 * Check for valid alternate path port number and fill
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
);
1633 return (IBT_HCA_PORT_INVALID
);
1637 * Check for valid alternate path PKey index and fill
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
;
1644 return (IBT_PKEY_IX_ILLEGAL
);
1646 opmask
|= HERMON_CMD_OP_ALT_PATH
;
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
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
,
1676 return (ibc_get_ci_failure(0));
1678 return (IBT_QP_STATE_INVALID
);
1682 return (DDI_SUCCESS
);
1687 * hermon_qp_rtr2rts()
1688 * Context: Can be called from interrupt or base context.
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;
1704 ASSERT(MUTEX_HELD(&qp
->qp_lock
));
1707 * Grab the temporary QPC entry from QP software state
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"
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"
1753 if (hermon_qp_validate_init_depth(state
, rc
, &sra_max
) !=
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
;
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
) {
1808 qpc_path
->ack_timeout
= rc
->rc_alt_path
.cep_timeout
;
1811 * Check for valid alternate path port number and fill
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
);
1821 return (IBT_HCA_PORT_INVALID
);
1825 * Check for valid alternate path PKey index and fill
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
;
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
;
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
) {
1890 qpc_path
->ack_timeout
= rc
->rc_alt_path
.cep_timeout
;
1893 * Check for valid alternate path port number and fill
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
);
1902 return (IBT_HCA_PORT_INVALID
);
1906 * Check for valid alternate path PKey index and fill
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
;
1913 return (IBT_PKEY_IX_ILLEGAL
);
1915 opmask
|= HERMON_CMD_OP_ALT_PATH
;
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
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
,
1945 return (ibc_get_ci_failure(0));
1947 return (IBT_QP_STATE_INVALID
);
1951 return (DDI_SUCCESS
);
1956 * hermon_qp_rts2rts()
1957 * Context: Can be called from interrupt or base context.
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;
1973 ASSERT(MUTEX_HELD(&qp
->qp_lock
));
1976 * Grab the temporary QPC entry from QP software state
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"
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
;
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
) {
2048 qpc_path
->ack_timeout
= rc
->rc_alt_path
.cep_timeout
;
2051 * Check for valid alternate path port number and fill
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
);
2061 return (IBT_HCA_PORT_INVALID
);
2065 * Check for valid alternate path PKey index and fill
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
;
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
;
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
) {
2123 * Check for valid alternate path port number and fill
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
);
2133 return (IBT_HCA_PORT_INVALID
);
2137 * Check for valid alternate path PKey index and fill
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
;
2144 return (IBT_PKEY_IX_ILLEGAL
);
2146 opmask
|= HERMON_CMD_OP_ALT_PATH
;
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
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
,
2176 return (ibc_get_ci_failure(0));
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.
2192 hermon_qp_rts2sqd(hermon_state_t
*state
, hermon_qphdl_t qp
,
2193 ibt_cep_modify_flags_t flags
)
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
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
,
2226 return (ibc_get_ci_failure(0));
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
);
2245 * hermon_qp_sqd2rts()
2246 * Context: Can be called from interrupt or base context.
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;
2263 ASSERT(MUTEX_HELD(&qp
->qp_lock
));
2266 * Grab the temporary QPC entry from QP software state
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
);
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
;
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"
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
;
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
) {
2366 qpc_path
->ack_timeout
= rc
->rc_alt_path
.cep_timeout
;
2368 * Check for valid alternate path port number and fill
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
);
2378 return (IBT_HCA_PORT_INVALID
);
2382 * Check for valid alternate path PKey index and fill
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
;
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"
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
;
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
) {
2482 * Check for valid alternate path port number and fill
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
);
2492 return (IBT_HCA_PORT_INVALID
);
2496 * Check for valid alternate path PKey index and fill
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
;
2503 return (IBT_PKEY_IX_ILLEGAL
);
2505 opmask
|= HERMON_CMD_OP_ALT_PATH
;
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
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
,
2535 return (ibc_get_ci_failure(0));
2537 return (IBT_QP_STATE_INVALID
);
2541 return (DDI_SUCCESS
);
2546 * hermon_qp_sqd2sqd()
2547 * Context: Can be called from interrupt or base context.
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;
2564 ASSERT(MUTEX_HELD(&qp
->qp_lock
));
2567 * Grab the temporary QPC entry from QP software state
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
);
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
;
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"
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
) {
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
);
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
;
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
;
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
);
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
) {
2737 qpc_path
->ack_timeout
= rc
->rc_alt_path
.cep_timeout
;
2740 * Check for valid alternate path port number and fill
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
);
2750 return (IBT_HCA_PORT_INVALID
);
2754 * Check for valid alternate path PKey index and fill
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
;
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"
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"
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
) {
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
);
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
;
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
;
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
) {
2933 * Check for valid alternate path port number and fill
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
);
2943 return (IBT_HCA_PORT_INVALID
);
2947 * Check for valid alternate path PKey index and fill
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
;
2954 return (IBT_PKEY_IX_ILLEGAL
);
2956 opmask
|= HERMON_CMD_OP_ALT_PATH
;
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
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
,
2986 return (ibc_get_ci_failure(0));
2988 return (IBT_QP_STATE_INVALID
);
2992 return (DDI_SUCCESS
);
2997 * hermon_qp_sqerr2rts()
2998 * Context: Can be called from interrupt or base context.
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;
3009 ASSERT(MUTEX_HELD(&qp
->qp_lock
));
3012 * Grab the temporary QPC entry from QP software state
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"
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
;
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
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
,
3073 return (ibc_get_ci_failure(0));
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.
3088 hermon_qp_to_error(hermon_state_t
*state
, hermon_qphdl_t qp
)
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
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
;
3127 ASSERT(MUTEX_HELD(&qp
->qp_lock
));
3130 * Grab the temporary QPC entry from QP software state
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
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.
3168 hermon_qp_reset2err(hermon_state_t
*state
, hermon_qphdl_t qp
)
3170 hermon_hw_qpc_t
*qpc
;
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
3193 * Fill in the common fields in the QPC
3195 if (qp
->qp_is_special
) {
3196 qpc
->serv_type
= HERMON_QP_MLX
;
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
;
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;
3219 (qp
->qp_sq_cqhdl
== NULL
) ? 0 : qp
->qp_sq_cqhdl
->cq_cqnum
& cqnmask
;
3220 qpc
->page_offs
= qp
->qp_wqinfo
.qa_pgoffs
>> 6;
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
;
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 */
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 */
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 */
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;
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
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.
3329 hermon_check_rdma_enable_flags(ibt_cep_modify_flags_t flags
,
3330 ibt_qp_info_t
*info_p
, hermon_hw_qpc_t
*qpc
)
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
;
3353 * hermon_qp_validate_resp_rsrc()
3354 * Context: Can be called from interrupt or base context.
3357 hermon_qp_validate_resp_rsrc(hermon_state_t
*state
, ibt_qp_rc_attr_t
*rc
,
3362 rdma_ra_in
= rc
->rc_rdma_ra_in
;
3365 * Check if number of responder resources is too large. Return an
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) {
3379 if (ISP2(rdma_ra_in
)) {
3380 *rra_max
= highbit(rdma_ra_in
) - 1;
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.
3393 hermon_qp_validate_init_depth(hermon_state_t
*state
, ibt_qp_rc_attr_t
*rc
,
3398 rdma_ra_out
= rc
->rc_rdma_ra_out
;
3401 * Check if requested initiator depth is too large. Return an error
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) {
3415 if (ISP2(rdma_ra_out
)) {
3416 *sra_max
= highbit(rdma_ra_out
) - 1;
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.
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
);