1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * hermon_qpmod.c
28 * Hermon Queue Pair Modify Routines
29 *
30 * This contains all the routines necessary to implement the
31 * ModifyQP() verb. This includes all the code for legal
32 * transitions to and from Reset, Init, RTR, RTS, SQD, SQErr,
33 * and Error.
34 */
35
36 #include <sys/sysmacros.h>
37 #include <sys/types.h>
38 #include <sys/conf.h>
39 #include <sys/ddi.h>
40 #include <sys/sunddi.h>
41 #include <sys/modctl.h>
42 #include <sys/bitmap.h>
43
44 #include <sys/ib/adapters/hermon/hermon.h>
45 #include <sys/ib/ib_pkt_hdrs.h>
46
47 static int hermon_qp_reset2init(hermon_state_t *state, hermon_qphdl_t qp,
48 ibt_qp_info_t *info_p);
49 static int hermon_qp_init2init(hermon_state_t *state, hermon_qphdl_t qp,
50 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
51 static int hermon_qp_init2rtr(hermon_state_t *state, hermon_qphdl_t qp,
52 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
53 static int hermon_qp_rtr2rts(hermon_state_t *state, hermon_qphdl_t qp,
54 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
55 static int hermon_qp_rts2rts(hermon_state_t *state, hermon_qphdl_t qp,
56 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
57 #ifdef HERMON_NOTNOW
58 static int hermon_qp_rts2sqd(hermon_state_t *state, hermon_qphdl_t qp,
59 ibt_cep_modify_flags_t flags);
60 #endif
61 static int hermon_qp_sqd2rts(hermon_state_t *state, hermon_qphdl_t qp,
62 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
63 static int hermon_qp_sqd2sqd(hermon_state_t *state, hermon_qphdl_t qp,
64 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
65 static int hermon_qp_sqerr2rts(hermon_state_t *state, hermon_qphdl_t qp,
66 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
67 static int hermon_qp_to_error(hermon_state_t *state, hermon_qphdl_t qp);
68 static int hermon_qp_reset2err(hermon_state_t *state, hermon_qphdl_t qp);
69
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);
77
78 /*
79 * hermon_qp_modify()
80 * Context: Can be called from interrupt or base context.
81 */
82 /* ARGSUSED */
83 int
hermon_qp_modify(hermon_state_t * state,hermon_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p,ibt_queue_sizes_t * actual_sz)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)
87 {
88 ibt_cep_state_t cur_state, mod_state;
89 ibt_cep_modify_flags_t okflags;
90 int status;
91
92 /*
93 * TODO add support for SUSPEND and RESUME
94 */
95
96 /*
97 * Lock the QP so that we can modify it atomically. After grabbing
98 * the lock, get the current QP state. We will use this current QP
99 * state to determine the legal transitions (and the checks that need
100 * to be performed.)
101 * Below is a case for every possible QP state. In each case, we
102 * check that no flags are set which are not valid for the possible
103 * transitions from that state. If these tests pass and the
104 * state transition we are attempting is legal, then we call one
105 * of the helper functions. Each of these functions does some
106 * additional setup before posting the firmware command for the
107 * appropriate state transition.
108 */
109 mutex_enter(&qp->qp_lock);
110
111 /*
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.
117 *
118 * Because callers specify part of a 'union' based on what QP type they
119 * think they're working with, this ensures that we do not pickup bogus
120 * data if the caller thought they were working with a different QP
121 * type.
122 */
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);
126 }
127
128 /*
129 * If this is a transition to RTS (which is valid from RTR, RTS,
130 * SQError, and SQ Drain) then we should honor the "current QP state"
131 * specified by the consumer. This means converting the IBTF QP state
132 * in "info_p->qp_current_state" to 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").
135 */
136 mod_state = info_p->qp_state;
137
138 if (flags & IBT_CEP_SET_RTR_RTS) {
139 cur_state = HERMON_QP_RTR; /* Ready to Receive */
140
141 } else if ((flags & IBT_CEP_SET_STATE) &&
142 (mod_state == IBT_STATE_RTS)) {
143
144 /* Convert the current IBTF QP state to an Hermon QP state */
145 switch (info_p->qp_current_state) {
146 case IBT_STATE_RTR:
147 cur_state = HERMON_QP_RTR; /* Ready to Receive */
148 break;
149 case IBT_STATE_RTS:
150 cur_state = HERMON_QP_RTS; /* Ready to Send */
151 break;
152 case IBT_STATE_SQE:
153 cur_state = HERMON_QP_SQERR; /* Send Queue Error */
154 break;
155 case IBT_STATE_SQD:
156 cur_state = HERMON_QP_SQD; /* SQ Drained */
157 break;
158 default:
159 mutex_exit(&qp->qp_lock);
160 return (IBT_QP_STATE_INVALID);
161 }
162 } else {
163 cur_state = qp->qp_state;
164 }
165
166 switch (cur_state) {
167 case HERMON_QP_RESET:
168 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_RESET_INIT |
169 IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W |
170 IBT_CEP_SET_ATOMIC | IBT_CEP_SET_PKEY_IX |
171 IBT_CEP_SET_PORT | IBT_CEP_SET_QKEY);
172
173 /*
174 * Check for attempts to modify invalid attributes from the
175 * "Reset" state
176 */
177 if (flags & ~okflags) {
178 mutex_exit(&qp->qp_lock);
179 status = IBT_QP_ATTR_RO;
180 goto qpmod_fail;
181 }
182
183 /*
184 * Verify state transition is to either "Init", back to
185 * "Reset", or to "Error".
186 */
187 if ((flags & IBT_CEP_SET_RESET_INIT) &&
188 (flags & IBT_CEP_SET_STATE) &&
189 (mod_state != IBT_STATE_INIT)) {
190 /* Invalid transition - ambiguous flags */
191 mutex_exit(&qp->qp_lock);
192 status = IBT_QP_STATE_INVALID;
193 goto qpmod_fail;
194
195 } else if ((flags & IBT_CEP_SET_RESET_INIT) ||
196 ((flags & IBT_CEP_SET_STATE) &&
197 (mod_state == IBT_STATE_INIT))) {
198 /*
199 * Attempt to transition from "Reset" to "Init"
200 */
201 status = hermon_qp_reset2init(state, qp, info_p);
202 if (status != DDI_SUCCESS) {
203 mutex_exit(&qp->qp_lock);
204 goto qpmod_fail;
205 }
206 qp->qp_state = HERMON_QP_INIT;
207 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_INIT);
208
209 } else if ((flags & IBT_CEP_SET_STATE) &&
210 (mod_state == IBT_STATE_RESET)) {
211 /*
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.
216 *
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.
221 */
222 mutex_exit(&qp->qp_lock);
223 return (DDI_SUCCESS);
224
225 } else if ((flags & IBT_CEP_SET_STATE) &&
226 (mod_state == IBT_STATE_ERROR)) {
227 /*
228 * Attempt to transition from "Reset" to "Error"
229 */
230 status = hermon_qp_reset2err(state, qp);
231 if (status != DDI_SUCCESS) {
232 mutex_exit(&qp->qp_lock);
233 goto qpmod_fail;
234 }
235 qp->qp_state = HERMON_QP_ERR;
236 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_ERR);
237
238 } else {
239 /* Invalid transition - return error */
240 mutex_exit(&qp->qp_lock);
241 status = IBT_QP_STATE_INVALID;
242 goto qpmod_fail;
243 }
244
245 /*
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.
253 */
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");
258 }
259 qp->qp_state = HERMON_QP_RESET;
260 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RESET);
261
262 mutex_exit(&qp->qp_lock);
263 goto qpmod_fail;
264 }
265 break;
266
267 case HERMON_QP_INIT:
268 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_INIT_RTR |
269 IBT_CEP_SET_ADDS_VECT | IBT_CEP_SET_RDMARA_IN |
270 IBT_CEP_SET_MIN_RNR_NAK | IBT_CEP_SET_ALT_PATH |
271 IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W |
272 IBT_CEP_SET_ATOMIC | IBT_CEP_SET_PKEY_IX |
273 IBT_CEP_SET_QKEY | IBT_CEP_SET_PORT);
274
275 /*
276 * Check for attempts to modify invalid attributes from the
277 * "Init" state
278 */
279 if (flags & ~okflags) {
280 mutex_exit(&qp->qp_lock);
281 status = IBT_QP_ATTR_RO;
282 goto qpmod_fail;
283 }
284
285 /*
286 * Verify state transition is to either "RTR", back to "Init",
287 * to "Reset", or to "Error"
288 */
289 if ((flags & IBT_CEP_SET_INIT_RTR) &&
290 (flags & IBT_CEP_SET_STATE) &&
291 (mod_state != IBT_STATE_RTR)) {
292 /* Invalid transition - ambiguous flags */
293 mutex_exit(&qp->qp_lock);
294 status = IBT_QP_STATE_INVALID;
295 goto qpmod_fail;
296
297 } else if ((flags & IBT_CEP_SET_INIT_RTR) ||
298 ((flags & IBT_CEP_SET_STATE) &&
299 (mod_state == IBT_STATE_RTR))) {
300 /*
301 * Attempt to transition from "Init" to "RTR"
302 */
303 status = hermon_qp_init2rtr(state, qp, flags, info_p);
304 if (status != DDI_SUCCESS) {
305 mutex_exit(&qp->qp_lock);
306 goto qpmod_fail;
307 }
308 qp->qp_state = HERMON_QP_RTR;
309 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RTR);
310
311 } else if ((flags & IBT_CEP_SET_STATE) &&
312 (mod_state == IBT_STATE_INIT)) {
313 /*
314 * Attempt to transition from "Init" to "Init"
315 */
316 status = hermon_qp_init2init(state, qp, flags, info_p);
317 if (status != DDI_SUCCESS) {
318 mutex_exit(&qp->qp_lock);
319 goto qpmod_fail;
320 }
321 qp->qp_state = HERMON_QP_INIT;
322 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_INIT);
323
324 } else if ((flags & IBT_CEP_SET_STATE) &&
325 (mod_state == IBT_STATE_RESET)) {
326 /*
327 * Attempt to transition from "Init" to "Reset"
328 */
329 status = hermon_qp_to_reset(state, qp);
330 if (status != DDI_SUCCESS) {
331 mutex_exit(&qp->qp_lock);
332 goto qpmod_fail;
333 }
334 qp->qp_state = HERMON_QP_RESET;
335 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RESET);
336
337 /*
338 * Do any additional handling necessary for the
339 * transition _to_ the "Reset" state (e.g. update the
340 * workQ WRID lists)
341 */
342 status = hermon_wrid_to_reset_handling(state, qp);
343 if (status != IBT_SUCCESS) {
344 mutex_exit(&qp->qp_lock);
345 goto qpmod_fail;
346 }
347
348 } else if ((flags & IBT_CEP_SET_STATE) &&
349 (mod_state == IBT_STATE_ERROR)) {
350 /*
351 * Attempt to transition from "Init" to "Error"
352 */
353 status = hermon_qp_to_error(state, qp);
354 if (status != DDI_SUCCESS) {
355 mutex_exit(&qp->qp_lock);
356 goto qpmod_fail;
357 }
358 qp->qp_state = HERMON_QP_ERR;
359 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_ERR);
360
361 } else {
362 /* Invalid transition - return error */
363 mutex_exit(&qp->qp_lock);
364 status = IBT_QP_STATE_INVALID;
365 goto qpmod_fail;
366 }
367 break;
368
369 case HERMON_QP_RTR:
370 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_RTR_RTS |
371 IBT_CEP_SET_TIMEOUT | IBT_CEP_SET_RETRY |
372 IBT_CEP_SET_RNR_NAK_RETRY | IBT_CEP_SET_RDMARA_OUT |
373 IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W |
374 IBT_CEP_SET_ATOMIC | IBT_CEP_SET_QKEY |
375 IBT_CEP_SET_ALT_PATH | IBT_CEP_SET_MIG |
376 IBT_CEP_SET_MIN_RNR_NAK);
377
378 /*
379 * Check for attempts to modify invalid attributes from the
380 * "RTR" state
381 */
382 if (flags & ~okflags) {
383 mutex_exit(&qp->qp_lock);
384 status = IBT_QP_ATTR_RO;
385 goto qpmod_fail;
386 }
387
388 /*
389 * Verify state transition is to either "RTS", "Reset",
390 * or "Error"
391 */
392 if ((flags & IBT_CEP_SET_RTR_RTS) &&
393 (flags & IBT_CEP_SET_STATE) &&
394 (mod_state != IBT_STATE_RTS)) {
395 /* Invalid transition - ambiguous flags */
396 mutex_exit(&qp->qp_lock);
397 status = IBT_QP_STATE_INVALID;
398 goto qpmod_fail;
399
400 } else if ((flags & IBT_CEP_SET_RTR_RTS) ||
401 ((flags & IBT_CEP_SET_STATE) &&
402 (mod_state == IBT_STATE_RTS))) {
403 /*
404 * Attempt to transition from "RTR" to "RTS"
405 */
406 status = hermon_qp_rtr2rts(state, qp, flags, info_p);
407 if (status != DDI_SUCCESS) {
408 mutex_exit(&qp->qp_lock);
409 goto qpmod_fail;
410 }
411 qp->qp_state = HERMON_QP_RTS;
412 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RTS);
413
414 } else if ((flags & IBT_CEP_SET_STATE) &&
415 (mod_state == IBT_STATE_RESET)) {
416 /*
417 * Attempt to transition from "RTR" to "Reset"
418 */
419 status = hermon_qp_to_reset(state, qp);
420 if (status != DDI_SUCCESS) {
421 mutex_exit(&qp->qp_lock);
422 goto qpmod_fail;
423 }
424 qp->qp_state = HERMON_QP_RESET;
425 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RESET);
426
427 /*
428 * Do any additional handling necessary for the
429 * transition _to_ the "Reset" state (e.g. update the
430 * workQ WRID lists)
431 */
432 status = hermon_wrid_to_reset_handling(state, qp);
433 if (status != IBT_SUCCESS) {
434 mutex_exit(&qp->qp_lock);
435 goto qpmod_fail;
436 }
437
438 } else if ((flags & IBT_CEP_SET_STATE) &&
439 (mod_state == IBT_STATE_ERROR)) {
440 /*
441 * Attempt to transition from "RTR" to "Error"
442 */
443 status = hermon_qp_to_error(state, qp);
444 if (status != DDI_SUCCESS) {
445 mutex_exit(&qp->qp_lock);
446 goto qpmod_fail;
447 }
448 qp->qp_state = HERMON_QP_ERR;
449 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_ERR);
450
451 } else {
452 /* Invalid transition - return error */
453 mutex_exit(&qp->qp_lock);
454 status = IBT_QP_STATE_INVALID;
455 goto qpmod_fail;
456 }
457 break;
458
459 case HERMON_QP_RTS:
460 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_RDMA_R |
461 IBT_CEP_SET_RDMA_W | IBT_CEP_SET_ATOMIC |
462 IBT_CEP_SET_QKEY | IBT_CEP_SET_ALT_PATH |
463 IBT_CEP_SET_MIG | IBT_CEP_SET_MIN_RNR_NAK |
464 IBT_CEP_SET_SQD_EVENT);
465
466 /*
467 * Check for attempts to modify invalid attributes from the
468 * "RTS" state
469 */
470 if (flags & ~okflags) {
471 mutex_exit(&qp->qp_lock);
472 status = IBT_QP_ATTR_RO;
473 goto qpmod_fail;
474 }
475
476 /*
477 * Verify state transition is to either "RTS", "SQD", "Reset",
478 * or "Error"
479 */
480 if ((flags & IBT_CEP_SET_STATE) &&
481 (mod_state == IBT_STATE_RTS)) {
482 /*
483 * Attempt to transition from "RTS" to "RTS"
484 */
485 status = hermon_qp_rts2rts(state, qp, flags, info_p);
486 if (status != DDI_SUCCESS) {
487 mutex_exit(&qp->qp_lock);
488 goto qpmod_fail;
489 }
490 qp->qp_state = HERMON_QP_RTS;
491 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RTS);
492
493 } else if ((flags & IBT_CEP_SET_STATE) &&
494 (mod_state == IBT_STATE_SQD)) {
495 #ifdef HERMON_NOTNOW
496 /*
497 * Attempt to transition from "RTS" to "SQD"
498 */
499 status = hermon_qp_rts2sqd(state, qp, flags);
500 if (status != DDI_SUCCESS) {
501 mutex_exit(&qp->qp_lock);
502 goto qpmod_fail;
503 }
504 qp->qp_state = HERMON_QP_SQD;
505 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_SQD);
506 #else
507 /* hack because of the lack of fw support for SQD */
508 mutex_exit(&qp->qp_lock);
509 status = IBT_QP_STATE_INVALID;
510 goto qpmod_fail;
511 #endif
512
513 } else if ((flags & IBT_CEP_SET_STATE) &&
514 (mod_state == IBT_STATE_RESET)) {
515 /*
516 * Attempt to transition from "RTS" to "Reset"
517 */
518 status = hermon_qp_to_reset(state, qp);
519 if (status != DDI_SUCCESS) {
520 mutex_exit(&qp->qp_lock);
521 goto qpmod_fail;
522 }
523 qp->qp_state = HERMON_QP_RESET;
524 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RESET);
525
526 /*
527 * Do any additional handling necessary for the
528 * transition _to_ the "Reset" state (e.g. update the
529 * workQ WRID lists)
530 */
531 status = hermon_wrid_to_reset_handling(state, qp);
532 if (status != IBT_SUCCESS) {
533 mutex_exit(&qp->qp_lock);
534 goto qpmod_fail;
535 }
536
537 } else if ((flags & IBT_CEP_SET_STATE) &&
538 (mod_state == IBT_STATE_ERROR)) {
539 /*
540 * Attempt to transition from "RTS" to "Error"
541 */
542 status = hermon_qp_to_error(state, qp);
543 if (status != DDI_SUCCESS) {
544 mutex_exit(&qp->qp_lock);
545 goto qpmod_fail;
546 }
547 qp->qp_state = HERMON_QP_ERR;
548 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_ERR);
549
550 } else {
551 /* Invalid transition - return error */
552 mutex_exit(&qp->qp_lock);
553 status = IBT_QP_STATE_INVALID;
554 goto qpmod_fail;
555 }
556 break;
557
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);
562
563 /*
564 * Check for attempts to modify invalid attributes from the
565 * "SQErr" state
566 */
567 if (flags & ~okflags) {
568 mutex_exit(&qp->qp_lock);
569 status = IBT_QP_ATTR_RO;
570 goto qpmod_fail;
571 }
572
573 /*
574 * Verify state transition is to either "RTS", "Reset", or
575 * "Error"
576 */
577 if ((flags & IBT_CEP_SET_STATE) &&
578 (mod_state == IBT_STATE_RTS)) {
579 /*
580 * Attempt to transition from "SQErr" to "RTS"
581 */
582 status = hermon_qp_sqerr2rts(state, qp, flags, info_p);
583 if (status != DDI_SUCCESS) {
584 mutex_exit(&qp->qp_lock);
585 goto qpmod_fail;
586 }
587 qp->qp_state = HERMON_QP_RTS;
588 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RTS);
589
590 } else if ((flags & IBT_CEP_SET_STATE) &&
591 (mod_state == IBT_STATE_RESET)) {
592 /*
593 * Attempt to transition from "SQErr" to "Reset"
594 */
595 status = hermon_qp_to_reset(state, qp);
596 if (status != DDI_SUCCESS) {
597 mutex_exit(&qp->qp_lock);
598 goto qpmod_fail;
599 }
600 qp->qp_state = HERMON_QP_RESET;
601 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RESET);
602
603 /*
604 * Do any additional handling necessary for the
605 * transition _to_ the "Reset" state (e.g. update the
606 * workQ WRID lists)
607 */
608 status = hermon_wrid_to_reset_handling(state, qp);
609 if (status != IBT_SUCCESS) {
610 mutex_exit(&qp->qp_lock);
611 goto qpmod_fail;
612 }
613
614 } else if ((flags & IBT_CEP_SET_STATE) &&
615 (mod_state == IBT_STATE_ERROR)) {
616 /*
617 * Attempt to transition from "SQErr" to "Error"
618 */
619 status = hermon_qp_to_error(state, qp);
620 if (status != DDI_SUCCESS) {
621 mutex_exit(&qp->qp_lock);
622 goto qpmod_fail;
623 }
624 qp->qp_state = HERMON_QP_ERR;
625 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_ERR);
626
627 } else {
628 /* Invalid transition - return error */
629 mutex_exit(&qp->qp_lock);
630 status = IBT_QP_STATE_INVALID;
631 goto qpmod_fail;
632 }
633 break;
634
635 case HERMON_QP_SQD:
636 okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_ADDS_VECT |
637 IBT_CEP_SET_ALT_PATH | IBT_CEP_SET_MIG |
638 IBT_CEP_SET_RDMARA_OUT | IBT_CEP_SET_RDMARA_IN |
639 IBT_CEP_SET_QKEY | IBT_CEP_SET_PKEY_IX |
640 IBT_CEP_SET_TIMEOUT | IBT_CEP_SET_RETRY |
641 IBT_CEP_SET_RNR_NAK_RETRY | IBT_CEP_SET_PORT |
642 IBT_CEP_SET_MIN_RNR_NAK | IBT_CEP_SET_RDMA_R |
643 IBT_CEP_SET_RDMA_W | IBT_CEP_SET_ATOMIC);
644
645 /*
646 * Check for attempts to modify invalid attributes from the
647 * "SQD" state
648 */
649 if (flags & ~okflags) {
650 mutex_exit(&qp->qp_lock);
651 status = IBT_QP_ATTR_RO;
652 goto qpmod_fail;
653 }
654
655 /*
656 * Verify state transition is to either "SQD", "RTS", "Reset",
657 * or "Error"
658 */
659
660 if ((flags & IBT_CEP_SET_STATE) &&
661 (mod_state == IBT_STATE_SQD)) {
662 /*
663 * Attempt to transition from "SQD" to "SQD"
664 */
665 status = hermon_qp_sqd2sqd(state, qp, flags, info_p);
666 if (status != DDI_SUCCESS) {
667 mutex_exit(&qp->qp_lock);
668 goto qpmod_fail;
669 }
670 qp->qp_state = HERMON_QP_SQD;
671 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_SQD);
672
673 } else if ((flags & IBT_CEP_SET_STATE) &&
674 (mod_state == IBT_STATE_RTS)) {
675 /*
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
680 */
681 if (qp->qp_sqd_still_draining) {
682 mutex_exit(&qp->qp_lock);
683 goto qpmod_fail;
684 }
685 /*
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.
690 *
691 * First, Attempt to transition from "SQD" to "SQD"
692 */
693 status = hermon_qp_sqd2sqd(state, qp, flags, info_p);
694 if (status != DDI_SUCCESS) {
695 mutex_exit(&qp->qp_lock);
696 goto qpmod_fail;
697 }
698 qp->qp_state = HERMON_QP_SQD;
699 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_SQD);
700
701 /*
702 * The, attempt to transition from "SQD" to "RTS", but
703 * request only the state transition, no attributes
704 */
705
706 status = hermon_qp_sqd2rts(state, qp,
707 IBT_CEP_SET_STATE, info_p);
708 if (status != DDI_SUCCESS) {
709 mutex_exit(&qp->qp_lock);
710 goto qpmod_fail;
711 }
712 qp->qp_state = HERMON_QP_RTS;
713 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RTS);
714
715 } else if ((flags & IBT_CEP_SET_STATE) &&
716 (mod_state == IBT_STATE_RESET)) {
717 /*
718 * Attempt to transition from "SQD" to "Reset"
719 */
720 status = hermon_qp_to_reset(state, qp);
721 if (status != DDI_SUCCESS) {
722 mutex_exit(&qp->qp_lock);
723 goto qpmod_fail;
724 }
725 qp->qp_state = HERMON_QP_RESET;
726 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RESET);
727
728 /*
729 * Do any additional handling necessary for the
730 * transition _to_ the "Reset" state (e.g. update the
731 * workQ WRID lists)
732 */
733 status = hermon_wrid_to_reset_handling(state, qp);
734 if (status != IBT_SUCCESS) {
735 mutex_exit(&qp->qp_lock);
736 goto qpmod_fail;
737 }
738
739 } else if ((flags & IBT_CEP_SET_STATE) &&
740 (mod_state == IBT_STATE_ERROR)) {
741 /*
742 * Attempt to transition from "SQD" to "Error"
743 */
744 status = hermon_qp_to_error(state, qp);
745 if (status != DDI_SUCCESS) {
746 mutex_exit(&qp->qp_lock);
747 goto qpmod_fail;
748 }
749 qp->qp_state = HERMON_QP_ERR;
750 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_ERR);
751
752 } else {
753 /* Invalid transition - return error */
754 mutex_exit(&qp->qp_lock);
755 status = IBT_QP_STATE_INVALID;
756 goto qpmod_fail;
757 }
758 break;
759
760 case HERMON_QP_ERR:
761 /*
762 * Verify state transition is to either "Reset" or back to
763 * "Error"
764 */
765 if ((flags & IBT_CEP_SET_STATE) &&
766 (mod_state == IBT_STATE_RESET)) {
767 /*
768 * Attempt to transition from "Error" to "Reset"
769 */
770 status = hermon_qp_to_reset(state, qp);
771 if (status != DDI_SUCCESS) {
772 mutex_exit(&qp->qp_lock);
773 goto qpmod_fail;
774 }
775 qp->qp_state = HERMON_QP_RESET;
776 HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RESET);
777
778 /*
779 * Do any additional handling necessary for the
780 * transition _to_ the "Reset" state (e.g. update the
781 * workQ WRID lists)
782 */
783 status = hermon_wrid_to_reset_handling(state, qp);
784 if (status != IBT_SUCCESS) {
785 mutex_exit(&qp->qp_lock);
786 goto qpmod_fail;
787 }
788
789 } else if ((flags & IBT_CEP_SET_STATE) &&
790 (mod_state == IBT_STATE_ERROR)) {
791 /*
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.
796 *
797 */
798 mutex_exit(&qp->qp_lock);
799 return (DDI_SUCCESS);
800
801 } else {
802 /* Invalid transition - return error */
803 mutex_exit(&qp->qp_lock);
804 status = IBT_QP_STATE_INVALID;
805 goto qpmod_fail;
806 }
807 break;
808
809 default:
810 /*
811 * Invalid QP state. If we got here then it's a warning of
812 * a probably serious problem. So print a message and return
813 * failure
814 */
815 mutex_exit(&qp->qp_lock);
816 HERMON_WARNING(state, "unknown QP state in modify");
817 status = IBT_QP_STATE_INVALID;
818 goto qpmod_fail;
819 }
820
821 mutex_exit(&qp->qp_lock);
822 return (DDI_SUCCESS);
823
824 qpmod_fail:
825 return (status);
826 }
827
828
829 /*
830 * hermon_qp_reset2init()
831 * Context: Can be called from interrupt or base context.
832 */
833 static int
hermon_qp_reset2init(hermon_state_t * state,hermon_qphdl_t qp,ibt_qp_info_t * info_p)834 hermon_qp_reset2init(hermon_state_t *state, hermon_qphdl_t qp,
835 ibt_qp_info_t *info_p)
836 {
837 hermon_hw_qpc_t *qpc;
838 ibt_qp_rc_attr_t *rc;
839 ibt_qp_ud_attr_t *ud;
840 ibt_qp_uc_attr_t *uc;
841 uint_t portnum, pkeyindx;
842 int status;
843 uint32_t cqnmask;
844 int qp_srq_en;
845
846 ASSERT(MUTEX_HELD(&qp->qp_lock));
847
848 /*
849 * Grab the temporary QPC entry from QP software state
850 */
851 qpc = &qp->qpc;
852
853 /*
854 * Fill in the common fields in the QPC
855 */
856
857 if (qp->qp_is_special) {
858 qpc->serv_type = HERMON_QP_MLX;
859 } else {
860 qpc->serv_type = qp->qp_serv_type;
861 }
862 qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
863
864 qpc->pd = qp->qp_pdhdl->pd_pdnum;
865
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;
871
872 qpc->usr_page = qp->qp_uarpg;
873
874 cqnmask = (1 << state->hs_cfg_profile->cp_log_num_cq) - 1;
875 qpc->cqn_snd =
876 (qp->qp_sq_cqhdl == NULL) ? 0 : qp->qp_sq_cqhdl->cq_cqnum & cqnmask;
877 qpc->page_offs = qp->qp_wqinfo.qa_pgoffs >> 6;
878 qpc->cqn_rcv =
879 (qp->qp_rq_cqhdl == NULL) ? 0 : qp->qp_rq_cqhdl->cq_cqnum & cqnmask;
880
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;
886 /*
887 * HERMON:
888 * qpc->wqe_baseaddr is replaced by LKey from the cMPT, and
889 * page_offset, mtt_base_addr_h/l, and log2_page_size will
890 * be used to map the WQE buffer
891 * NOTE that the cMPT is created implicitly when the QP is
892 * transitioned from reset to init
893 */
894 qpc->log2_pgsz = qp->qp_mrhdl->mr_log2_pgsz;
895 qpc->mtt_base_addrl = (qp->qp_mrhdl->mr_mttaddr) >> 3;
896 qpc->mtt_base_addrh = (uint32_t)((qp->qp_mrhdl->mr_mttaddr >> 32) &
897 0xFF);
898 qp_srq_en = (qp->qp_alloc_flags & IBT_QP_USES_SRQ) != 0;
899 qpc->srq_en = qp_srq_en;
900
901 if (qp_srq_en) {
902 qpc->srq_number = qp->qp_srqhdl->srq_srqnum;
903 } else {
904 qpc->srq_number = 0;
905 }
906
907 /*
908 * Fast Registration Work Requests and Reserved Lkey are enabled
909 * with the single IBT bit stored in qp_rlky.
910 */
911 qpc->fre = qp->qp_rlky;
912 qpc->rlky = qp->qp_rlky;
913
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 */
918
919 /*
920 * Now fill in the QPC fields which are specific to transport type
921 */
922 if (qp->qp_type == IBT_UD_RQP) {
923 int my_fc_id_idx, exch_base;
924
925 ud = &info_p->qp_transport.ud;
926
927 /* Set the QKey */
928 qpc->qkey = ud->ud_qkey;
929
930 /*
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.
934 */
935 qpc->mtu = HERMON_MAX_MTU;
936 if (qp->qp_uses_lso)
937 qpc->msg_max = state->hs_devlim.log_max_gso_sz;
938 else if (qp->qp_is_special)
939 qpc->msg_max = HERMON_MAX_MTU + 6;
940 else
941 qpc->msg_max = HERMON_QP_LOG_MAX_MSGSZ;
942
943 /* Check for valid port number and fill it in */
944 portnum = ud->ud_port;
945 if (hermon_portnum_is_valid(state, portnum)) {
946 qp->qp_portnum = portnum - 1;
947 qpc->pri_addr_path.sched_q =
948 HERMON_QP_SCHEDQ_GET(portnum - 1,
949 0, qp->qp_is_special);
950 } else {
951 return (IBT_HCA_PORT_INVALID);
952 }
953
954
955 /* Check for valid PKey index and fill it in */
956 pkeyindx = ud->ud_pkey_ix;
957 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
958 qpc->pri_addr_path.pkey_indx = pkeyindx;
959 qp->qp_pkeyindx = pkeyindx;
960 } else {
961 return (IBT_PKEY_IX_ILLEGAL);
962 }
963
964 /* fill in the RSS fields */
965 if (qpc->rss) {
966 struct hermon_hw_rss_s *rssp;
967 ibt_rss_flags_t flags = ud->ud_rss.rss_flags;
968
969 rssp = (struct hermon_hw_rss_s *)&qpc->pri_addr_path;
970 rssp->log2_tbl_sz = ud->ud_rss.rss_log2_table;
971 rssp->base_qpn = ud->ud_rss.rss_base_qpn;
972 rssp->default_qpn = ud->ud_rss.rss_def_qpn;
973 if (flags & IBT_RSS_ALG_XOR)
974 rssp->hash_fn = 0; /* XOR Hash Function */
975 else if (flags & IBT_RSS_ALG_TPL)
976 rssp->hash_fn = 1; /* Toeplitz Hash Fn */
977 else
978 return (IBT_INVALID_PARAM);
979 rssp->ipv4 = (flags & IBT_RSS_HASH_IPV4) != 0;
980 rssp->tcp_ipv4 = (flags & IBT_RSS_HASH_TCP_IPV4) != 0;
981 rssp->ipv6 = (flags & IBT_RSS_HASH_IPV6) != 0;
982 rssp->tcp_ipv4 = (flags & IBT_RSS_HASH_TCP_IPV6) != 0;
983 bcopy(ud->ud_rss.rss_toe_key, rssp->rss_key, 40);
984 } else if (qp->qp_serv_type == HERMON_QP_RFCI) {
985 status = hermon_fcoib_set_id(state, portnum,
986 qp->qp_qpnum, ud->ud_fc.fc_src_id);
987 if (status != DDI_SUCCESS)
988 return (status);
989 qp->qp_fc_attr = ud->ud_fc;
990 } else if (qp->qp_serv_type == HERMON_QP_FEXCH) {
991 my_fc_id_idx = hermon_fcoib_get_id_idx(state,
992 portnum, &ud->ud_fc);
993 if (my_fc_id_idx == -1)
994 return (IBT_INVALID_PARAM);
995 qpc->my_fc_id_idx = my_fc_id_idx;
996
997 status = hermon_fcoib_fexch_mkey_init(state,
998 qp->qp_pdhdl, ud->ud_fc.fc_hca_port,
999 qp->qp_qpnum, HERMON_CMD_NOSLEEP_SPIN);
1000 if (status != DDI_SUCCESS)
1001 return (status);
1002 qp->qp_fc_attr = ud->ud_fc;
1003 } else if (qp->qp_serv_type == HERMON_QP_FCMND) {
1004 my_fc_id_idx = hermon_fcoib_get_id_idx(state,
1005 portnum, &ud->ud_fc);
1006 if (my_fc_id_idx == -1)
1007 return (IBT_INVALID_PARAM);
1008 qpc->my_fc_id_idx = my_fc_id_idx;
1009 exch_base = hermon_fcoib_check_exch_base_off(state,
1010 portnum, &ud->ud_fc);
1011 if (exch_base == -1)
1012 return (IBT_INVALID_PARAM);
1013 qpc->exch_base = exch_base;
1014 qpc->exch_size = ud->ud_fc.fc_exch_log2_sz;
1015 qp->qp_fc_attr = ud->ud_fc;
1016 }
1017
1018 } else if (qp->qp_serv_type == HERMON_QP_RC) {
1019 rc = &info_p->qp_transport.rc;
1020
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;
1025
1026 /* Check for valid port number and fill it in */
1027 portnum = rc->rc_path.cep_hca_port_num;
1028 if (hermon_portnum_is_valid(state, portnum)) {
1029 qp->qp_portnum = portnum - 1;
1030 qpc->pri_addr_path.sched_q =
1031 HERMON_QP_SCHEDQ_GET(portnum - 1,
1032 0, qp->qp_is_special);
1033 } else {
1034 return (IBT_HCA_PORT_INVALID);
1035 }
1036
1037 /* Check for valid PKey index and fill it in */
1038 pkeyindx = rc->rc_path.cep_pkey_ix;
1039 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1040 qpc->pri_addr_path.pkey_indx = pkeyindx;
1041 } else {
1042 return (IBT_PKEY_IX_ILLEGAL);
1043 }
1044
1045 } else if (qp->qp_serv_type == HERMON_QP_UC) {
1046 uc = &info_p->qp_transport.uc;
1047
1048 /*
1049 * Set the RDMA (recv) enable/disable flags. Note: RDMA Read
1050 * and Atomic are ignored by default.
1051 */
1052 qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
1053
1054 /* Check for valid port number and fill it in */
1055 portnum = uc->uc_path.cep_hca_port_num;
1056 if (hermon_portnum_is_valid(state, portnum)) {
1057 qp->qp_portnum = portnum - 1;
1058 qpc->pri_addr_path.sched_q =
1059 HERMON_QP_SCHEDQ_GET(portnum - 1,
1060 0, qp->qp_is_special);
1061 } else {
1062 return (IBT_HCA_PORT_INVALID);
1063 }
1064
1065 /* Check for valid PKey index and fill it in */
1066 pkeyindx = uc->uc_path.cep_pkey_ix;
1067 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1068 qpc->pri_addr_path.pkey_indx = pkeyindx;
1069 } else {
1070 return (IBT_PKEY_IX_ILLEGAL);
1071 }
1072
1073 } else {
1074 /*
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
1078 */
1079 HERMON_WARNING(state, "unknown QP transport type in rst2init");
1080 return (ibc_get_ci_failure(0));
1081 }
1082
1083 /*
1084 * Post the RST2INIT_QP command to the Hermon firmware
1085 *
1086 * We do a HERMON_NOSLEEP here because we are still holding the
1087 * "qp_lock". If we got raised to interrupt level by priority
1088 * inversion, we do not want to block in this routine waiting for
1089 * success.
1090 */
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);
1098 }
1099 return (ibc_get_ci_failure(0));
1100 }
1101
1102 return (DDI_SUCCESS);
1103 }
1104
1105
1106 /*
1107 * hermon_qp_init2init()
1108 * Context: Can be called from interrupt or base context.
1109 */
1110 static int
hermon_qp_init2init(hermon_state_t * state,hermon_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p)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)
1113 {
1114 hermon_hw_qpc_t *qpc;
1115 ibt_qp_rc_attr_t *rc;
1116 ibt_qp_ud_attr_t *ud;
1117 ibt_qp_uc_attr_t *uc;
1118 uint_t portnum, pkeyindx;
1119 uint32_t opmask = 0;
1120 int status;
1121
1122 ASSERT(MUTEX_HELD(&qp->qp_lock));
1123
1124 /*
1125 * Grab the temporary QPC entry from QP software state
1126 */
1127 qpc = &qp->qpc;
1128
1129 /*
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.
1132 */
1133 if (qp->qp_type == IBT_UD_RQP) {
1134 ud = &info_p->qp_transport.ud;
1135
1136 /*
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.
1140 */
1141 /*
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
1146 */
1147 if (flags & IBT_CEP_SET_PORT) {
1148 portnum = ud->ud_port;
1149 if (hermon_portnum_is_valid(state, portnum)) {
1150 qp->qp_portnum = portnum - 1; /* save it away */
1151 qpc->pri_addr_path.sched_q =
1152 HERMON_QP_SCHEDQ_GET(portnum - 1,
1153 0, qp->qp_is_special);
1154 } else {
1155 return (IBT_HCA_PORT_INVALID);
1156 }
1157 }
1158
1159 /*
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.
1163 */
1164 if (flags & IBT_CEP_SET_PKEY_IX) {
1165 pkeyindx = ud->ud_pkey_ix;
1166 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1167 qpc->pri_addr_path.pkey_indx = pkeyindx;
1168 opmask |= HERMON_CMD_OP_PKEYINDX;
1169 qp->qp_pkeyindx = pkeyindx;
1170 } else {
1171 return (IBT_PKEY_IX_ILLEGAL);
1172 }
1173 }
1174
1175 /*
1176 * If we are attempting to modify the QKey for this QP, then
1177 * fill it in and set the appropriate flag in the "opmask"
1178 * parameter.
1179 */
1180 if (flags & IBT_CEP_SET_QKEY) {
1181 qpc->qkey = ud->ud_qkey;
1182 opmask |= HERMON_CMD_OP_QKEY;
1183 }
1184
1185 } else if (qp->qp_serv_type == HERMON_QP_RC) {
1186 rc = &info_p->qp_transport.rc;
1187
1188 /*
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.
1192 */
1193 if (flags & IBT_CEP_SET_PORT) {
1194 portnum = rc->rc_path.cep_hca_port_num;
1195 if (hermon_portnum_is_valid(state, portnum)) {
1196 qp->qp_portnum = portnum - 1;
1197 qpc->pri_addr_path.sched_q =
1198 HERMON_QP_SCHEDQ_GET(portnum - 1,
1199 0, qp->qp_is_special);
1200 } else {
1201 return (IBT_HCA_PORT_INVALID);
1202 }
1203
1204 }
1205
1206 /*
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.
1210 */
1211 if (flags & IBT_CEP_SET_PKEY_IX) {
1212 pkeyindx = rc->rc_path.cep_pkey_ix;
1213 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1214 qpc->pri_addr_path.pkey_indx = pkeyindx;
1215 opmask |= HERMON_CMD_OP_PKEYINDX;
1216 } else {
1217 return (IBT_PKEY_IX_ILLEGAL);
1218 }
1219 }
1220
1221 /*
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
1225 */
1226 opmask |= hermon_check_rdma_enable_flags(flags, info_p, qpc);
1227
1228 } else if (qp->qp_serv_type == HERMON_QP_UC) {
1229 uc = &info_p->qp_transport.uc;
1230
1231 /*
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.
1235 */
1236 if (flags & IBT_CEP_SET_PORT) {
1237 portnum = uc->uc_path.cep_hca_port_num;
1238 if (hermon_portnum_is_valid(state, portnum)) {
1239 qp->qp_portnum = portnum - 1;
1240 qpc->pri_addr_path.sched_q =
1241 HERMON_QP_SCHEDQ_GET(portnum - 1,
1242 0, qp->qp_is_special);
1243 } else {
1244 return (IBT_HCA_PORT_INVALID);
1245 }
1246 /* port# cannot be set in this transition - defer to init2rtr */
1247 }
1248
1249 /*
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.
1253 */
1254 if (flags & IBT_CEP_SET_PKEY_IX) {
1255 pkeyindx = uc->uc_path.cep_pkey_ix;
1256 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1257 qpc->pri_addr_path.pkey_indx = pkeyindx;
1258 opmask |= HERMON_CMD_OP_PKEYINDX;
1259 } else {
1260 return (IBT_PKEY_IX_ILLEGAL);
1261 }
1262 }
1263
1264 /*
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.
1269 */
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;
1273 }
1274 } else {
1275 /*
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
1279 */
1280 HERMON_WARNING(state, "unknown QP transport type in init2init");
1281 return (ibc_get_ci_failure(0));
1282 }
1283
1284 /*
1285 * Post the INIT2INIT_QP command to the Hermon firmware
1286 *
1287 * We do a HERMON_NOSLEEP here because we are still holding the
1288 * "qp_lock". If we got raised to interrupt level by priority
1289 * inversion, we do not want to block in this routine waiting for
1290 * success.
1291 */
1292 status = hermon_cmn_qp_cmd_post(state, INIT2INIT_QP, qpc, qp->qp_qpnum,
1293 opmask, HERMON_CMD_NOSLEEP_SPIN);
1294 if (status != HERMON_CMD_SUCCESS) {
1295 if (status != HERMON_CMD_BAD_QP_STATE) {
1296 cmn_err(CE_NOTE, "hermon%d: INIT2INIT_QP command "
1297 "failed: %08x\n", state->hs_instance, status);
1298 if (status == HERMON_CMD_INVALID_STATUS) {
1299 hermon_fm_ereport(state, HCA_SYS_ERR,
1300 HCA_ERR_SRV_LOST);
1301 }
1302 return (ibc_get_ci_failure(0));
1303 } else {
1304 return (IBT_QP_STATE_INVALID);
1305 }
1306 }
1307
1308 return (DDI_SUCCESS);
1309 }
1310
1311
1312 /*
1313 * hermon_qp_init2rtr()
1314 * Context: Can be called from interrupt or base context.
1315 */
1316 static int
hermon_qp_init2rtr(hermon_state_t * state,hermon_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p)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)
1319 {
1320 hermon_hw_qpc_t *qpc;
1321 ibt_qp_rc_attr_t *rc;
1322 ibt_qp_ud_attr_t *ud;
1323 ibt_qp_uc_attr_t *uc;
1324 hermon_hw_addr_path_t *qpc_path;
1325 ibt_adds_vect_t *adds_vect;
1326 uint_t portnum, pkeyindx, rra_max;
1327 uint_t mtu;
1328 uint32_t opmask = 0;
1329 int status;
1330
1331 ASSERT(MUTEX_HELD(&qp->qp_lock));
1332
1333 /*
1334 * Grab the temporary QPC entry from QP software state
1335 */
1336 qpc = &qp->qpc;
1337
1338 /*
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.
1341 */
1342 if (qp->qp_type == IBT_UD_RQP) {
1343 ud = &info_p->qp_transport.ud;
1344
1345 /*
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.
1350 */
1351 qpc->mtu = HERMON_MAX_MTU;
1352 if (qp->qp_uses_lso)
1353 qpc->msg_max = state->hs_devlim.log_max_gso_sz;
1354 else
1355 qpc->msg_max = HERMON_QP_LOG_MAX_MSGSZ;
1356
1357 /*
1358 * Save away the MTU value. This is used in future sqd2sqd
1359 * transitions, as the MTU must remain the same in future
1360 * changes.
1361 */
1362 qp->qp_save_mtu = qpc->mtu;
1363
1364 /*
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.
1368 */
1369 if (flags & IBT_CEP_SET_PKEY_IX) {
1370 pkeyindx = ud->ud_pkey_ix;
1371 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1372 qpc->pri_addr_path.pkey_indx = pkeyindx;
1373 opmask |= HERMON_CMD_OP_PKEYINDX;
1374 qp->qp_pkeyindx = pkeyindx;
1375 } else {
1376 return (IBT_PKEY_IX_ILLEGAL);
1377 }
1378 }
1379
1380 /*
1381 * If we are attempting to modify the QKey for this QP, then
1382 * fill it in and set the appropriate flag in the "opmask"
1383 * parameter.
1384 */
1385 if (flags & IBT_CEP_SET_QKEY) {
1386 qpc->qkey = ud->ud_qkey;
1387 opmask |= HERMON_CMD_OP_QKEY;
1388 }
1389
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;
1394
1395 /*
1396 * Set the common primary address path fields
1397 */
1398 status = hermon_set_addr_path(state, adds_vect, qpc_path,
1399 HERMON_ADDRPATH_QP);
1400 if (status != DDI_SUCCESS) {
1401 return (status);
1402 }
1403 /* set the primary port number/sched_q */
1404 portnum = qp->qp_portnum + 1;
1405 if (hermon_portnum_is_valid(state, portnum)) {
1406 qpc->pri_addr_path.sched_q =
1407 HERMON_QP_SCHEDQ_GET(qp->qp_portnum,
1408 adds_vect->av_srvl, qp->qp_is_special);
1409 } else {
1410 return (IBT_HCA_PORT_INVALID);
1411 }
1412
1413 /*
1414 * The following values are apparently "required" here (as
1415 * they are part of the IBA-defined "Remote Node Address
1416 * Vector"). However, they are also going to be "required"
1417 * later - at RTR2RTS_QP time. Not sure why. But we set
1418 * them here anyway.
1419 */
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;
1423
1424 /*
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.
1429 */
1430 qpc->rem_qpn = rc->rc_dst_qpn;
1431 qpc->next_rcv_psn = rc->rc_rq_psn;
1432 qpc->msg_max = HERMON_QP_LOG_MAX_MSGSZ;
1433 qpc->ric = 0;
1434 mtu = rc->rc_path_mtu;
1435
1436 if (hermon_qp_validate_mtu(state, mtu) != DDI_SUCCESS) {
1437 return (IBT_HCA_PORT_MTU_EXCEEDED);
1438 }
1439 qpc->mtu = mtu;
1440
1441 /*
1442 * Save away the MTU value. This is used in future sqd2sqd
1443 * transitions, as the MTU must remain the same in future
1444 * changes.
1445 */
1446 qp->qp_save_mtu = qpc->mtu;
1447
1448 /*
1449 * Though it is a "required" parameter, "min_rnr_nak" is
1450 * optionally specifiable in Hermon. So we force the
1451 * optional flag here.
1452 */
1453 qpc->min_rnr_nak = rc->rc_min_rnr_nak;
1454 opmask |= HERMON_CMD_OP_MINRNRNAK;
1455
1456 /*
1457 * Check that the number of specified "incoming RDMA resources"
1458 * is valid. And if it is, then setup the "rra_max
1459 */
1460 if (hermon_qp_validate_resp_rsrc(state, rc, &rra_max) !=
1461 DDI_SUCCESS) {
1462 return (IBT_INVALID_PARAM);
1463 }
1464 qpc->rra_max = rra_max;
1465
1466 /* don't need to set up ra_buff_indx, implicit for hermon */
1467
1468 /*
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.
1472 */
1473 if (flags & IBT_CEP_SET_PKEY_IX) {
1474 pkeyindx = rc->rc_path.cep_pkey_ix;
1475 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1476 qpc->pri_addr_path.pkey_indx = pkeyindx;
1477 opmask |= HERMON_CMD_OP_PKEYINDX;
1478 } else {
1479 return (IBT_PKEY_IX_ILLEGAL);
1480 }
1481 }
1482
1483 /*
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
1487 */
1488 opmask |= hermon_check_rdma_enable_flags(flags, info_p, qpc);
1489
1490 /*
1491 * Check for optional alternate path and fill in the
1492 * appropriate QPC fields if one is specified
1493 */
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;
1497
1498 /* Set the common alternate address path fields */
1499 status = hermon_set_addr_path(state, adds_vect,
1500 qpc_path, HERMON_ADDRPATH_QP);
1501 if (status != DDI_SUCCESS) {
1502 return (status);
1503 }
1504 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
1505
1506
1507 /*
1508 * Check for valid alternate path port number and fill
1509 * it in
1510 */
1511 portnum = rc->rc_alt_path.cep_hca_port_num;
1512 if (hermon_portnum_is_valid(state, portnum)) {
1513 qp->qp_portnum_alt = portnum - 1;
1514 qpc->alt_addr_path.sched_q =
1515 HERMON_QP_SCHEDQ_GET(portnum - 1,
1516 adds_vect->av_srvl, qp->qp_is_special);
1517 } else {
1518 return (IBT_HCA_PORT_INVALID);
1519 }
1520 /*
1521 * Check for valid alternate path PKey index and fill
1522 * it in
1523 */
1524 pkeyindx = rc->rc_alt_path.cep_pkey_ix;
1525 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1526 qpc->alt_addr_path.pkey_indx = pkeyindx;
1527 } else {
1528 return (IBT_PKEY_IX_ILLEGAL);
1529 }
1530 opmask |= HERMON_CMD_OP_ALT_PATH;
1531 }
1532
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;
1537
1538 /*
1539 * Set the common primary address path fields
1540 */
1541 status = hermon_set_addr_path(state, adds_vect, qpc_path,
1542 HERMON_ADDRPATH_QP);
1543 if (status != DDI_SUCCESS) {
1544 return (status);
1545 }
1546
1547 /* set the primary port num/schedq */
1548 portnum = qp->qp_portnum + 1;
1549 if (hermon_portnum_is_valid(state, portnum)) {
1550 qpc->pri_addr_path.sched_q =
1551 HERMON_QP_SCHEDQ_GET(qp->qp_portnum,
1552 adds_vect->av_srvl, qp->qp_is_special);
1553 } else {
1554 return (IBT_HCA_PORT_INVALID);
1555 }
1556
1557 /*
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.
1562 */
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);
1569 }
1570 qpc->mtu = mtu;
1571
1572 /*
1573 * Save away the MTU value. This is used in future sqd2sqd
1574 * transitions, as the MTU must remain the same in future
1575 * changes.
1576 */
1577 qp->qp_save_mtu = qpc->mtu;
1578
1579 /*
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.
1583 */
1584 if (flags & IBT_CEP_SET_PKEY_IX) {
1585 pkeyindx = uc->uc_path.cep_pkey_ix;
1586 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1587 qpc->pri_addr_path.pkey_indx = pkeyindx;
1588 opmask |= HERMON_CMD_OP_PKEYINDX;
1589 } else {
1590 return (IBT_PKEY_IX_ILLEGAL);
1591 }
1592 }
1593
1594 /*
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.
1599 */
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;
1603 }
1604
1605 /*
1606 * Check for optional alternate path and fill in the
1607 * appropriate QPC fields if one is specified
1608 */
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;
1612
1613 /* Set the common alternate address path fields */
1614 status = hermon_set_addr_path(state, adds_vect,
1615 qpc_path, HERMON_ADDRPATH_QP);
1616 if (status != DDI_SUCCESS) {
1617 return (status);
1618 }
1619
1620 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
1621
1622 /*
1623 * Check for valid alternate path port number and fill
1624 * it in
1625 */
1626 portnum = uc->uc_alt_path.cep_hca_port_num;
1627 if (hermon_portnum_is_valid(state, portnum)) {
1628 qp->qp_portnum_alt = portnum - 1;
1629 qpc->alt_addr_path.sched_q =
1630 HERMON_QP_SCHEDQ_GET(portnum - 1,
1631 adds_vect->av_srvl, qp->qp_is_special);
1632 } else {
1633 return (IBT_HCA_PORT_INVALID);
1634 }
1635
1636 /*
1637 * Check for valid alternate path PKey index and fill
1638 * it in
1639 */
1640 pkeyindx = uc->uc_alt_path.cep_pkey_ix;
1641 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1642 qpc->alt_addr_path.pkey_indx = pkeyindx;
1643 } else {
1644 return (IBT_PKEY_IX_ILLEGAL);
1645 }
1646 opmask |= HERMON_CMD_OP_ALT_PATH;
1647 }
1648 } else {
1649 /*
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
1653 */
1654 HERMON_WARNING(state, "unknown QP transport type in init2rtr");
1655 return (ibc_get_ci_failure(0));
1656 }
1657
1658 /*
1659 * Post the INIT2RTR_QP command to the Hermon firmware
1660 *
1661 * We do a HERMON_NOSLEEP here because we are still holding the
1662 * "qp_lock". If we got raised to interrupt level by priority
1663 * inversion, we do not want to block in this routine waiting for
1664 * success.
1665 */
1666 status = hermon_cmn_qp_cmd_post(state, INIT2RTR_QP, qpc, qp->qp_qpnum,
1667 opmask, HERMON_CMD_NOSLEEP_SPIN);
1668 if (status != HERMON_CMD_SUCCESS) {
1669 if (status != HERMON_CMD_BAD_QP_STATE) {
1670 cmn_err(CE_NOTE, "hermon%d: INIT2RTR_QP command "
1671 "failed: %08x\n", state->hs_instance, status);
1672 if (status == HERMON_CMD_INVALID_STATUS) {
1673 hermon_fm_ereport(state, HCA_SYS_ERR,
1674 HCA_ERR_SRV_LOST);
1675 }
1676 return (ibc_get_ci_failure(0));
1677 } else {
1678 return (IBT_QP_STATE_INVALID);
1679 }
1680 }
1681
1682 return (DDI_SUCCESS);
1683 }
1684
1685
1686 /*
1687 * hermon_qp_rtr2rts()
1688 * Context: Can be called from interrupt or base context.
1689 */
1690 static int
hermon_qp_rtr2rts(hermon_state_t * state,hermon_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p)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)
1693 {
1694 hermon_hw_qpc_t *qpc;
1695 ibt_qp_rc_attr_t *rc;
1696 ibt_qp_ud_attr_t *ud;
1697 ibt_qp_uc_attr_t *uc;
1698 hermon_hw_addr_path_t *qpc_path;
1699 ibt_adds_vect_t *adds_vect;
1700 uint_t portnum, pkeyindx, sra_max;
1701 uint32_t opmask = 0;
1702 int status;
1703
1704 ASSERT(MUTEX_HELD(&qp->qp_lock));
1705
1706 /*
1707 * Grab the temporary QPC entry from QP software state
1708 */
1709 qpc = &qp->qpc;
1710
1711 /*
1712 * Now fill in the QPC fields which are specific to transport type
1713 */
1714 if (qp->qp_type == IBT_UD_RQP) {
1715 ud = &info_p->qp_transport.ud;
1716
1717 /* Set the send PSN */
1718 qpc->next_snd_psn = ud->ud_sq_psn;
1719
1720 /*
1721 * If we are attempting to modify the QKey for this QP, then
1722 * fill it in and set the appropriate flag in the "opmask"
1723 * parameter.
1724 */
1725 if (flags & IBT_CEP_SET_QKEY) {
1726 qpc->qkey = ud->ud_qkey;
1727 opmask |= HERMON_CMD_OP_QKEY;
1728 }
1729
1730 } else if (qp->qp_serv_type == HERMON_QP_RC) {
1731 rc = &info_p->qp_transport.rc;
1732 qpc_path = &qpc->pri_addr_path;
1733
1734 /*
1735 * Setup the send PSN, ACK timeout, and retry counts
1736 */
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;
1742
1743 /*
1744 * Set "ack_req_freq" based on the configuration variable
1745 */
1746 qpc->ack_req_freq = state->hs_cfg_profile->cp_ackreq_freq;
1747
1748 /*
1749 * Check that the number of specified "outgoing RDMA resources"
1750 * is valid. And if it is, then setup the "sra_max"
1751 * appropriately
1752 */
1753 if (hermon_qp_validate_init_depth(state, rc, &sra_max) !=
1754 DDI_SUCCESS) {
1755 return (IBT_INVALID_PARAM);
1756 }
1757 qpc->sra_max = sra_max;
1758
1759
1760 /*
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
1764 */
1765 opmask |= hermon_check_rdma_enable_flags(flags, info_p, qpc);
1766
1767 /*
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.
1771 */
1772 if (flags & IBT_CEP_SET_MIG) {
1773 if (rc->rc_mig_state == IBT_STATE_MIGRATED) {
1774 qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
1775 } else if (rc->rc_mig_state == IBT_STATE_REARMED) {
1776 qpc->pm_state = HERMON_QP_PMSTATE_REARM;
1777 } else {
1778 return (IBT_QP_APM_STATE_INVALID);
1779 }
1780 opmask |= HERMON_CMD_OP_PM_STATE;
1781 }
1782
1783 /*
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.
1787 */
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;
1791 }
1792
1793 /*
1794 * Check for optional alternate path and fill in the
1795 * appropriate QPC fields if one is specified
1796 */
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;
1800
1801 /* Set the common alternate address path fields */
1802 status = hermon_set_addr_path(state, adds_vect,
1803 qpc_path, HERMON_ADDRPATH_QP);
1804 if (status != DDI_SUCCESS) {
1805 return (status);
1806 }
1807
1808 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
1809
1810 /*
1811 * Check for valid alternate path port number and fill
1812 * it in
1813 */
1814 portnum = rc->rc_alt_path.cep_hca_port_num;
1815 if (hermon_portnum_is_valid(state, portnum)) {
1816 qp->qp_portnum_alt = portnum - 1;
1817 qpc->alt_addr_path.sched_q =
1818 HERMON_QP_SCHEDQ_GET(portnum - 1,
1819 adds_vect->av_srvl, qp->qp_is_special);
1820 } else {
1821 return (IBT_HCA_PORT_INVALID);
1822 }
1823
1824 /*
1825 * Check for valid alternate path PKey index and fill
1826 * it in
1827 */
1828 pkeyindx = rc->rc_alt_path.cep_pkey_ix;
1829 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1830 qpc->alt_addr_path.pkey_indx = pkeyindx;
1831 } else {
1832 return (IBT_PKEY_IX_ILLEGAL);
1833 }
1834 opmask |= HERMON_CMD_OP_ALT_PATH;
1835 }
1836
1837 } else if (qp->qp_serv_type == HERMON_QP_UC) {
1838 uc = &info_p->qp_transport.uc;
1839
1840 /* Set the send PSN */
1841 qpc->next_snd_psn = uc->uc_sq_psn;
1842
1843 /*
1844 * Configure the QP to allow (sending of) all types of allowable
1845 * UC traffic (i.e. RDMA Write).
1846 */
1847
1848
1849 /*
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.
1854 */
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;
1858 }
1859
1860 /*
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.
1864 */
1865 if (flags & IBT_CEP_SET_MIG) {
1866 if (uc->uc_mig_state == IBT_STATE_MIGRATED) {
1867 qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
1868 } else if (uc->uc_mig_state == IBT_STATE_REARMED) {
1869 qpc->pm_state = HERMON_QP_PMSTATE_REARM;
1870 } else {
1871 return (IBT_QP_APM_STATE_INVALID);
1872 }
1873 opmask |= HERMON_CMD_OP_PM_STATE;
1874 }
1875
1876 /*
1877 * Check for optional alternate path and fill in the
1878 * appropriate QPC fields if one is specified
1879 */
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;
1883
1884 /* Set the common alternate address path fields */
1885 status = hermon_set_addr_path(state, adds_vect,
1886 qpc_path, HERMON_ADDRPATH_QP);
1887 if (status != DDI_SUCCESS) {
1888 return (status);
1889 }
1890 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
1891
1892 /*
1893 * Check for valid alternate path port number and fill
1894 * it in
1895 */
1896 portnum = uc->uc_alt_path.cep_hca_port_num;
1897 if (hermon_portnum_is_valid(state, portnum)) {
1898 qpc->alt_addr_path.sched_q =
1899 HERMON_QP_SCHEDQ_GET(portnum - 1,
1900 adds_vect->av_srvl, qp->qp_is_special);
1901 } else {
1902 return (IBT_HCA_PORT_INVALID);
1903 }
1904
1905 /*
1906 * Check for valid alternate path PKey index and fill
1907 * it in
1908 */
1909 pkeyindx = uc->uc_alt_path.cep_pkey_ix;
1910 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
1911 qpc->alt_addr_path.pkey_indx = pkeyindx;
1912 } else {
1913 return (IBT_PKEY_IX_ILLEGAL);
1914 }
1915 opmask |= HERMON_CMD_OP_ALT_PATH;
1916 }
1917 } else {
1918 /*
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
1922 */
1923 HERMON_WARNING(state, "unknown QP transport type in rtr2rts");
1924 return (ibc_get_ci_failure(0));
1925 }
1926
1927 /*
1928 * Post the RTR2RTS_QP command to the Hermon firmware
1929 *
1930 * We do a HERMON_NOSLEEP here because we are still holding the
1931 * "qp_lock". If we got raised to interrupt level by priority
1932 * inversion, we do not want to block in this routine waiting for
1933 * success.
1934 */
1935 status = hermon_cmn_qp_cmd_post(state, RTR2RTS_QP, qpc, qp->qp_qpnum,
1936 opmask, HERMON_CMD_NOSLEEP_SPIN);
1937 if (status != HERMON_CMD_SUCCESS) {
1938 if (status != HERMON_CMD_BAD_QP_STATE) {
1939 cmn_err(CE_NOTE, "hermon%d: RTR2RTS_QP command failed: "
1940 "%08x\n", state->hs_instance, status);
1941 if (status == HERMON_CMD_INVALID_STATUS) {
1942 hermon_fm_ereport(state, HCA_SYS_ERR,
1943 HCA_ERR_SRV_LOST);
1944 }
1945 return (ibc_get_ci_failure(0));
1946 } else {
1947 return (IBT_QP_STATE_INVALID);
1948 }
1949 }
1950
1951 return (DDI_SUCCESS);
1952 }
1953
1954
1955 /*
1956 * hermon_qp_rts2rts()
1957 * Context: Can be called from interrupt or base context.
1958 */
1959 static int
hermon_qp_rts2rts(hermon_state_t * state,hermon_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p)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)
1962 {
1963 hermon_hw_qpc_t *qpc;
1964 ibt_qp_rc_attr_t *rc;
1965 ibt_qp_ud_attr_t *ud;
1966 ibt_qp_uc_attr_t *uc;
1967 hermon_hw_addr_path_t *qpc_path;
1968 ibt_adds_vect_t *adds_vect;
1969 uint_t portnum, pkeyindx;
1970 uint32_t opmask = 0;
1971 int status;
1972
1973 ASSERT(MUTEX_HELD(&qp->qp_lock));
1974
1975 /*
1976 * Grab the temporary QPC entry from QP software state
1977 */
1978
1979 qpc = &qp->qpc;
1980
1981 /*
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.
1984 */
1985 if (qp->qp_type == IBT_UD_RQP) {
1986 ud = &info_p->qp_transport.ud;
1987
1988 /*
1989 * If we are attempting to modify the QKey for this QP, then
1990 * fill it in and set the appropriate flag in the "opmask"
1991 * parameter.
1992 */
1993 if (flags & IBT_CEP_SET_QKEY) {
1994 qpc->qkey = ud->ud_qkey;
1995 opmask |= HERMON_CMD_OP_QKEY;
1996 }
1997
1998 } else if (qp->qp_serv_type == HERMON_QP_RC) {
1999 rc = &info_p->qp_transport.rc;
2000
2001 /*
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
2005 */
2006 opmask |= hermon_check_rdma_enable_flags(flags, info_p, qpc);
2007
2008 /*
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.
2012 */
2013 if (flags & IBT_CEP_SET_MIG) {
2014 if (rc->rc_mig_state == IBT_STATE_MIGRATED) {
2015 qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
2016 } else if (rc->rc_mig_state == IBT_STATE_REARMED) {
2017 qpc->pm_state = HERMON_QP_PMSTATE_REARM;
2018 } else {
2019 return (IBT_QP_APM_STATE_INVALID);
2020 }
2021 opmask |= HERMON_CMD_OP_PM_STATE;
2022 }
2023
2024 /*
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.
2028 */
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;
2032 }
2033
2034 /*
2035 * Check for optional alternate path and fill in the
2036 * appropriate QPC fields if one is specified
2037 */
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;
2041
2042 /* Set the common alternate address path fields */
2043 status = hermon_set_addr_path(state, adds_vect,
2044 qpc_path, HERMON_ADDRPATH_QP);
2045 if (status != DDI_SUCCESS) {
2046 return (status);
2047 }
2048 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
2049
2050 /*
2051 * Check for valid alternate path port number and fill
2052 * it in
2053 */
2054 portnum = rc->rc_alt_path.cep_hca_port_num;
2055 if (hermon_portnum_is_valid(state, portnum)) {
2056 qp->qp_portnum_alt = portnum - 1;
2057 qpc->alt_addr_path.sched_q =
2058 HERMON_QP_SCHEDQ_GET(portnum - 1,
2059 adds_vect->av_srvl, qp->qp_is_special);
2060 } else {
2061 return (IBT_HCA_PORT_INVALID);
2062 }
2063
2064 /*
2065 * Check for valid alternate path PKey index and fill
2066 * it in
2067 */
2068 pkeyindx = rc->rc_alt_path.cep_pkey_ix;
2069 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
2070 qpc->alt_addr_path.pkey_indx = pkeyindx;
2071 } else {
2072 return (IBT_PKEY_IX_ILLEGAL);
2073 }
2074 opmask |= HERMON_CMD_OP_ALT_PATH;
2075 }
2076
2077 } else if (qp->qp_serv_type == HERMON_QP_UC) {
2078 uc = &info_p->qp_transport.uc;
2079
2080 /*
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.
2085 */
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;
2089 }
2090
2091 /*
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.
2095 */
2096 if (flags & IBT_CEP_SET_MIG) {
2097 if (uc->uc_mig_state == IBT_STATE_MIGRATED) {
2098 qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
2099 } else if (uc->uc_mig_state == IBT_STATE_REARMED) {
2100 qpc->pm_state = HERMON_QP_PMSTATE_REARM;
2101 } else {
2102 return (IBT_QP_APM_STATE_INVALID);
2103 }
2104 opmask |= HERMON_CMD_OP_PM_STATE;
2105 }
2106
2107 /*
2108 * Check for optional alternate path and fill in the
2109 * appropriate QPC fields if one is specified
2110 */
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;
2114
2115 /* Set the common alternate address path fields */
2116 status = hermon_set_addr_path(state, adds_vect,
2117 qpc_path, HERMON_ADDRPATH_QP);
2118 if (status != DDI_SUCCESS) {
2119 return (status);
2120 }
2121
2122 /*
2123 * Check for valid alternate path port number and fill
2124 * it in
2125 */
2126 portnum = uc->uc_alt_path.cep_hca_port_num;
2127 if (hermon_portnum_is_valid(state, portnum)) {
2128 qp->qp_portnum_alt = portnum - 1;
2129 qpc->alt_addr_path.sched_q =
2130 HERMON_QP_SCHEDQ_GET(portnum - 1,
2131 adds_vect->av_srvl, qp->qp_is_special);
2132 } else {
2133 return (IBT_HCA_PORT_INVALID);
2134 }
2135
2136 /*
2137 * Check for valid alternate path PKey index and fill
2138 * it in
2139 */
2140 pkeyindx = uc->uc_alt_path.cep_pkey_ix;
2141 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
2142 qpc->alt_addr_path.pkey_indx = pkeyindx;
2143 } else {
2144 return (IBT_PKEY_IX_ILLEGAL);
2145 }
2146 opmask |= HERMON_CMD_OP_ALT_PATH;
2147 }
2148 } else {
2149 /*
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
2153 */
2154 HERMON_WARNING(state, "unknown QP transport type in rts2rts");
2155 return (ibc_get_ci_failure(0));
2156 }
2157
2158 /*
2159 * Post the RTS2RTS_QP command to the Hermon firmware
2160 *
2161 * We do a HERMON_NOSLEEP here because we are still holding the
2162 * "qp_lock". If we got raised to interrupt level by priority
2163 * inversion, we do not want to block in this routine waiting for
2164 * success.
2165 */
2166 status = hermon_cmn_qp_cmd_post(state, RTS2RTS_QP, qpc, qp->qp_qpnum,
2167 opmask, HERMON_CMD_NOSLEEP_SPIN);
2168 if (status != HERMON_CMD_SUCCESS) {
2169 if (status != HERMON_CMD_BAD_QP_STATE) {
2170 cmn_err(CE_NOTE, "hermon%d: RTS2RTS_QP command failed: "
2171 "%08x\n", state->hs_instance, status);
2172 if (status == HERMON_CMD_INVALID_STATUS) {
2173 hermon_fm_ereport(state, HCA_SYS_ERR,
2174 HCA_ERR_SRV_LOST);
2175 }
2176 return (ibc_get_ci_failure(0));
2177 } else {
2178 return (IBT_QP_STATE_INVALID);
2179 }
2180 }
2181
2182 return (DDI_SUCCESS);
2183 }
2184
2185
2186 #ifdef HERMON_NOTNOW
2187 /*
2188 * hermon_qp_rts2sqd()
2189 * Context: Can be called from interrupt or base context.
2190 */
2191 static int
hermon_qp_rts2sqd(hermon_state_t * state,hermon_qphdl_t qp,ibt_cep_modify_flags_t flags)2192 hermon_qp_rts2sqd(hermon_state_t *state, hermon_qphdl_t qp,
2193 ibt_cep_modify_flags_t flags)
2194 {
2195 int status;
2196
2197 ASSERT(MUTEX_HELD(&qp->qp_lock));
2198
2199 /*
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.
2205 */
2206 qp->qp_forward_sqd_event = (flags & IBT_CEP_SET_SQD_EVENT) ? 1 : 0;
2207
2208 /*
2209 * Post the RTS2SQD_QP command to the Hermon firmware
2210 *
2211 * We do a HERMON_NOSLEEP here because we are still holding the
2212 * "qp_lock". If we got raised to interrupt level by priority
2213 * inversion, we do not want to block in this routine waiting for
2214 * success.
2215 */
2216 status = hermon_cmn_qp_cmd_post(state, RTS2SQD_QP, NULL, qp->qp_qpnum,
2217 0, HERMON_CMD_NOSLEEP_SPIN);
2218 if (status != HERMON_CMD_SUCCESS) {
2219 if (status != HERMON_CMD_BAD_QP_STATE) {
2220 cmn_err(CE_NOTE, "hermon%d: RTS2SQD_QP command failed: "
2221 "%08x\n", state->hs_instance, status);
2222 if (status == HERMON_CMD_INVALID_STATUS) {
2223 hermon_fm_ereport(state, HCA_SYS_ERR,
2224 HCA_ERR_SRV_LOST);
2225 }
2226 return (ibc_get_ci_failure(0));
2227 } else {
2228 return (IBT_QP_STATE_INVALID);
2229 }
2230 }
2231
2232 /*
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)
2236 */
2237 qp->qp_sqd_still_draining = 1;
2238
2239 return (DDI_SUCCESS);
2240 }
2241 #endif
2242
2243
2244 /*
2245 * hermon_qp_sqd2rts()
2246 * Context: Can be called from interrupt or base context.
2247 */
2248 static int
hermon_qp_sqd2rts(hermon_state_t * state,hermon_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p)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)
2251 {
2252 hermon_hw_qpc_t *qpc;
2253 ibt_qp_rc_attr_t *rc;
2254 ibt_qp_ud_attr_t *ud;
2255 ibt_qp_uc_attr_t *uc;
2256 hermon_hw_addr_path_t *qpc_path;
2257 ibt_adds_vect_t *adds_vect;
2258 uint_t portnum, pkeyindx;
2259 uint_t rra_max, sra_max;
2260 uint32_t opmask = 0;
2261 int status;
2262
2263 ASSERT(MUTEX_HELD(&qp->qp_lock));
2264
2265 /*
2266 * Grab the temporary QPC entry from QP software state
2267 */
2268 qpc = &qp->qpc;
2269
2270 /*
2271 * Fill in the common fields in the QPC
2272 */
2273
2274 /*
2275 * Now fill in the QPC fields which are specific to transport type
2276 */
2277 if (qp->qp_type == IBT_UD_RQP) {
2278 ud = &info_p->qp_transport.ud;
2279
2280 /*
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.
2284 */
2285 if (flags & IBT_CEP_SET_PORT) {
2286 portnum = ud->ud_port;
2287 if (hermon_portnum_is_valid(state, portnum)) {
2288 qp->qp_portnum = portnum - 1;
2289 qpc->pri_addr_path.sched_q =
2290 HERMON_QP_SCHEDQ_GET(portnum - 1,
2291 0, qp->qp_is_special);
2292 } else {
2293 return (IBT_HCA_PORT_INVALID);
2294 }
2295 opmask |= HERMON_CMD_OP_PRIM_PORT;
2296 }
2297
2298 /*
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.
2302 */
2303 if (flags & IBT_CEP_SET_PKEY_IX) {
2304 pkeyindx = ud->ud_pkey_ix;
2305 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
2306 qpc->pri_addr_path.pkey_indx = pkeyindx;
2307 opmask |= HERMON_CMD_OP_PKEYINDX;
2308 qp->qp_pkeyindx = pkeyindx;
2309 } else {
2310 return (IBT_PKEY_IX_ILLEGAL);
2311 }
2312 }
2313
2314 /*
2315 * If we are attempting to modify the QKey for this QP, then
2316 * fill it in and set the appropriate flag in the "opmask"
2317 * parameter.
2318 */
2319 if (flags & IBT_CEP_SET_QKEY) {
2320 qpc->qkey = ud->ud_qkey;
2321 opmask |= HERMON_CMD_OP_QKEY;
2322 }
2323
2324 } else if (qp->qp_serv_type == HERMON_QP_RC) {
2325 rc = &info_p->qp_transport.rc;
2326
2327 /*
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
2331 */
2332 opmask |= hermon_check_rdma_enable_flags(flags, info_p, qpc);
2333
2334 qpc->retry_cnt = rc->rc_retry_cnt;
2335
2336 /*
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.
2340 */
2341 if (flags & IBT_CEP_SET_MIG) {
2342 if (rc->rc_mig_state == IBT_STATE_MIGRATED) {
2343 qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
2344 } else if (rc->rc_mig_state == IBT_STATE_REARMED) {
2345 qpc->pm_state = HERMON_QP_PMSTATE_REARM;
2346 } else {
2347 return (IBT_QP_APM_STATE_INVALID);
2348 }
2349 opmask |= HERMON_CMD_OP_PM_STATE;
2350 }
2351
2352 /*
2353 * Check for optional alternate path and fill in the
2354 * appropriate QPC fields if one is specified
2355 */
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;
2359
2360 /* Set the common alternate address path fields */
2361 status = hermon_set_addr_path(state, adds_vect,
2362 qpc_path, HERMON_ADDRPATH_QP);
2363 if (status != DDI_SUCCESS) {
2364 return (status);
2365 }
2366 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
2367 /*
2368 * Check for valid alternate path port number and fill
2369 * it in
2370 */
2371 portnum = rc->rc_alt_path.cep_hca_port_num;
2372 if (hermon_portnum_is_valid(state, portnum)) {
2373 qp->qp_portnum_alt = portnum - 1;
2374 qpc->alt_addr_path.sched_q =
2375 HERMON_QP_SCHEDQ_GET(portnum - 1,
2376 adds_vect->av_srvl, qp->qp_is_special);
2377 } else {
2378 return (IBT_HCA_PORT_INVALID);
2379 }
2380
2381 /*
2382 * Check for valid alternate path PKey index and fill
2383 * it in
2384 */
2385 pkeyindx = rc->rc_alt_path.cep_pkey_ix;
2386 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
2387 qpc->alt_addr_path.pkey_indx = pkeyindx;
2388 } else {
2389 return (IBT_PKEY_IX_ILLEGAL);
2390 }
2391 opmask |= HERMON_CMD_OP_ALT_PATH;
2392 }
2393
2394 /*
2395 * If we are attempting to modify the number of "outgoing
2396 * RDMA resources" for this QP, then check for valid value and
2397 * fill it in. Also set the appropriate flag in the "opmask"
2398 * parameter.
2399 */
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);
2404 }
2405 qpc->sra_max = sra_max;
2406 opmask |= HERMON_CMD_OP_SRA_SET;
2407 }
2408
2409 /*
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.
2415 */
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);
2420 }
2421 qpc->rra_max = rra_max;
2422 opmask |= HERMON_CMD_OP_RRA_SET;
2423 }
2424
2425
2426 /*
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.
2430 */
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;
2434 }
2435
2436 } else if (qp->qp_serv_type == HERMON_QP_UC) {
2437 uc = &info_p->qp_transport.uc;
2438
2439 /*
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.
2444 */
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;
2448 }
2449
2450 /*
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.
2454 */
2455 if (flags & IBT_CEP_SET_MIG) {
2456 if (uc->uc_mig_state == IBT_STATE_MIGRATED) {
2457 qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
2458 } else if (uc->uc_mig_state == IBT_STATE_REARMED) {
2459 qpc->pm_state = HERMON_QP_PMSTATE_REARM;
2460 } else {
2461 return (IBT_QP_APM_STATE_INVALID);
2462 }
2463 opmask |= HERMON_CMD_OP_PM_STATE;
2464 }
2465
2466 /*
2467 * Check for optional alternate path and fill in the
2468 * appropriate QPC fields if one is specified
2469 */
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;
2473
2474 /* Set the common alternate address path fields */
2475 status = hermon_set_addr_path(state, adds_vect,
2476 qpc_path, HERMON_ADDRPATH_QP);
2477 if (status != DDI_SUCCESS) {
2478 return (status);
2479 }
2480
2481 /*
2482 * Check for valid alternate path port number and fill
2483 * it in
2484 */
2485 portnum = uc->uc_alt_path.cep_hca_port_num;
2486 if (hermon_portnum_is_valid(state, portnum)) {
2487 qp->qp_portnum_alt = portnum - 1;
2488 qpc->alt_addr_path.sched_q =
2489 HERMON_QP_SCHEDQ_GET(portnum - 1,
2490 adds_vect->av_srvl, qp->qp_is_special);
2491 } else {
2492 return (IBT_HCA_PORT_INVALID);
2493 }
2494
2495 /*
2496 * Check for valid alternate path PKey index and fill
2497 * it in
2498 */
2499 pkeyindx = uc->uc_alt_path.cep_pkey_ix;
2500 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
2501 qpc->alt_addr_path.pkey_indx = pkeyindx;
2502 } else {
2503 return (IBT_PKEY_IX_ILLEGAL);
2504 }
2505 opmask |= HERMON_CMD_OP_ALT_PATH;
2506 }
2507 } else {
2508 /*
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
2512 */
2513 HERMON_WARNING(state, "unknown QP transport type in sqd2rts");
2514 return (ibc_get_ci_failure(0));
2515 }
2516
2517 /*
2518 * Post the SQD2RTS_QP command to the Hermon firmware
2519 *
2520 * We do a HERMON_NOSLEEP here because we are still holding the
2521 * "qp_lock". If we got raised to interrupt level by priority
2522 * inversion, we do not want to block in this routine waiting for
2523 * success.
2524 */
2525 status = hermon_cmn_qp_cmd_post(state, SQD2RTS_QP, qpc, qp->qp_qpnum,
2526 opmask, HERMON_CMD_NOSLEEP_SPIN);
2527 if (status != HERMON_CMD_SUCCESS) {
2528 if (status != HERMON_CMD_BAD_QP_STATE) {
2529 cmn_err(CE_NOTE, "hermon%d: SQD2RTS_QP command failed: "
2530 "%08x\n", state->hs_instance, status);
2531 if (status == HERMON_CMD_INVALID_STATUS) {
2532 hermon_fm_ereport(state, HCA_SYS_ERR,
2533 HCA_ERR_SRV_LOST);
2534 }
2535 return (ibc_get_ci_failure(0));
2536 } else {
2537 return (IBT_QP_STATE_INVALID);
2538 }
2539 }
2540
2541 return (DDI_SUCCESS);
2542 }
2543
2544
2545 /*
2546 * hermon_qp_sqd2sqd()
2547 * Context: Can be called from interrupt or base context.
2548 */
2549 static int
hermon_qp_sqd2sqd(hermon_state_t * state,hermon_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p)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)
2552 {
2553 hermon_hw_qpc_t *qpc;
2554 ibt_qp_rc_attr_t *rc;
2555 ibt_qp_ud_attr_t *ud;
2556 ibt_qp_uc_attr_t *uc;
2557 hermon_hw_addr_path_t *qpc_path;
2558 ibt_adds_vect_t *adds_vect;
2559 uint_t portnum, pkeyindx;
2560 uint_t rra_max, sra_max;
2561 uint32_t opmask = 0;
2562 int status;
2563
2564 ASSERT(MUTEX_HELD(&qp->qp_lock));
2565
2566 /*
2567 * Grab the temporary QPC entry from QP software state
2568 */
2569 qpc = &qp->qpc;
2570
2571 /*
2572 * Fill in the common fields in the QPC
2573 */
2574
2575 /*
2576 * Now fill in the QPC fields which are specific to transport type
2577 */
2578 if (qp->qp_type == IBT_UD_RQP) {
2579 ud = &info_p->qp_transport.ud;
2580
2581 /*
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.
2585 */
2586 if (flags & IBT_CEP_SET_PORT) {
2587 portnum = ud->ud_port;
2588 if (hermon_portnum_is_valid(state, portnum)) {
2589 qp->qp_portnum = portnum - 1;
2590 qpc->pri_addr_path.sched_q =
2591 HERMON_QP_SCHEDQ_GET(portnum - 1,
2592 0, qp->qp_is_special);
2593 } else {
2594 return (IBT_HCA_PORT_INVALID);
2595 }
2596 opmask |= HERMON_CMD_OP_SCHEDQUEUE;
2597 }
2598
2599 /*
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.
2603 */
2604 if (flags & IBT_CEP_SET_PKEY_IX) {
2605 pkeyindx = ud->ud_pkey_ix;
2606 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
2607 qpc->pri_addr_path.pkey_indx = pkeyindx;
2608 opmask |= HERMON_CMD_OP_PKEYINDX;
2609 qp->qp_pkeyindx = pkeyindx;
2610 } else {
2611 return (IBT_PKEY_IX_ILLEGAL);
2612 }
2613 }
2614
2615 /*
2616 * If we are attempting to modify the QKey for this QP, then
2617 * fill it in and set the appropriate flag in the "opmask"
2618 * parameter.
2619 */
2620 if (flags & IBT_CEP_SET_QKEY) {
2621 qpc->qkey = ud->ud_qkey;
2622 opmask |= HERMON_CMD_OP_QKEY;
2623 }
2624
2625 } else if (qp->qp_serv_type == HERMON_QP_RC) {
2626 rc = &info_p->qp_transport.rc;
2627
2628 /*
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
2632 */
2633 opmask |= hermon_check_rdma_enable_flags(flags, info_p, qpc);
2634
2635 /*
2636 * Check for optional primary path and fill in the
2637 * appropriate QPC fields if one is specified
2638 */
2639 if (flags & IBT_CEP_SET_ADDS_VECT) {
2640 qpc_path = &qpc->pri_addr_path;
2641 adds_vect = &rc->rc_path.cep_adds_vect;
2642
2643 /* Set the common primary address path fields */
2644 status = hermon_set_addr_path(state, adds_vect,
2645 qpc_path, HERMON_ADDRPATH_QP);
2646 if (status != DDI_SUCCESS) {
2647 return (status);
2648 }
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;
2652
2653 portnum = qp->qp_portnum + 1;
2654 if (hermon_portnum_is_valid(state, portnum)) {
2655 qpc->pri_addr_path.sched_q =
2656 HERMON_QP_SCHEDQ_GET(qp->qp_portnum,
2657 adds_vect->av_srvl, qp->qp_is_special);
2658 } else {
2659 return (IBT_HCA_PORT_INVALID);
2660 }
2661
2662 /*
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.
2666 */
2667 qpc->mtu = qp->qp_save_mtu;
2668
2669 opmask |= (HERMON_CMD_OP_PRIM_PATH |
2670 HERMON_CMD_OP_RETRYCNT | HERMON_CMD_OP_ACKTIMEOUT |
2671 HERMON_CMD_OP_PRIM_RNRRETRY);
2672 }
2673
2674 /*
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.
2678 */
2679 if (flags & IBT_CEP_SET_MIG) {
2680 if (rc->rc_mig_state == IBT_STATE_MIGRATED) {
2681 qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
2682 } else if (rc->rc_mig_state == IBT_STATE_REARMED) {
2683 qpc->pm_state = HERMON_QP_PMSTATE_REARM;
2684 } else {
2685 return (IBT_QP_APM_STATE_INVALID);
2686 }
2687 opmask |= HERMON_CMD_OP_PM_STATE;
2688 }
2689
2690 /*
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.
2694 */
2695 if (flags & IBT_CEP_SET_PKEY_IX) {
2696 pkeyindx = rc->rc_path.cep_pkey_ix;
2697 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
2698 qpc->pri_addr_path.pkey_indx = pkeyindx;
2699 opmask |= HERMON_CMD_OP_PKEYINDX;
2700 } else {
2701 return (IBT_PKEY_IX_ILLEGAL);
2702 }
2703 }
2704
2705 /*
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.
2709 */
2710 if (flags & IBT_CEP_SET_PORT) {
2711 portnum = rc->rc_path.cep_hca_port_num;
2712 if (hermon_portnum_is_valid(state, portnum)) {
2713 qp->qp_portnum = portnum - 1;
2714 qpc->pri_addr_path.sched_q =
2715 HERMON_QP_SCHEDQ_GET(portnum - 1,
2716 adds_vect->av_srvl, qp->qp_is_special);
2717 } else {
2718 return (IBT_HCA_PORT_INVALID);
2719 }
2720 opmask |= HERMON_CMD_OP_SCHEDQUEUE;
2721 }
2722
2723 /*
2724 * Check for optional alternate path and fill in the
2725 * appropriate QPC fields if one is specified
2726 */
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;
2730
2731 /* Set the common alternate address path fields */
2732 status = hermon_set_addr_path(state, adds_vect,
2733 qpc_path, HERMON_ADDRPATH_QP);
2734 if (status != DDI_SUCCESS) {
2735 return (status);
2736 }
2737 qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
2738
2739 /*
2740 * Check for valid alternate path port number and fill
2741 * it in
2742 */
2743 portnum = rc->rc_alt_path.cep_hca_port_num;
2744 if (hermon_portnum_is_valid(state, portnum)) {
2745 qp->qp_portnum_alt = portnum - 1;
2746 qpc->alt_addr_path.sched_q =
2747 HERMON_QP_SCHEDQ_GET(portnum - 1,
2748 adds_vect->av_srvl, qp->qp_is_special);
2749 } else {
2750 return (IBT_HCA_PORT_INVALID);
2751 }
2752
2753 /*
2754 * Check for valid alternate path PKey index and fill
2755 * it in
2756 */
2757 pkeyindx = rc->rc_alt_path.cep_pkey_ix;
2758 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
2759 qpc->alt_addr_path.pkey_indx = pkeyindx;
2760 } else {
2761 return (IBT_PKEY_IX_ILLEGAL);
2762 }
2763 opmask |= HERMON_CMD_OP_ALT_PATH;
2764 }
2765
2766 /*
2767 * If we are attempting to modify the number of "outgoing
2768 * RDMA resources" for this QP, then check for valid value and
2769 * fill it in. Also set the appropriate flag in the "opmask"
2770 * parameter.
2771 */
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);
2776 }
2777 qpc->sra_max = sra_max;
2778 opmask |= HERMON_CMD_OP_SRA_SET;
2779 }
2780
2781 /*
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.
2787 */
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);
2792 }
2793 qpc->rra_max = rra_max;
2794 opmask |= HERMON_CMD_OP_RRA_SET;
2795 }
2796
2797 /*
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.
2801 */
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;
2806 }
2807
2808 /*
2809 * If we are attempting to modify the "Retry Count" for this QP,
2810 * then fill it in and set the appropriate flag in the "opmask"
2811 * parameter.
2812 */
2813 if (flags & IBT_CEP_SET_RETRY) {
2814 qpc->retry_cnt = rc->rc_retry_cnt;
2815 opmask |= HERMON_CMD_OP_PRIM_RNRRETRY;
2816 }
2817
2818 /*
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.
2822 */
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;
2827 }
2828
2829 /*
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.
2833 */
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;
2837 }
2838
2839 } else if (qp->qp_serv_type == HERMON_QP_UC) {
2840 uc = &info_p->qp_transport.uc;
2841
2842 /*
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.
2847 */
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;
2851 }
2852
2853 /*
2854 * Check for optional primary path and fill in the
2855 * appropriate QPC fields if one is specified
2856 */
2857 if (flags & IBT_CEP_SET_ADDS_VECT) {
2858 qpc_path = &qpc->pri_addr_path;
2859 adds_vect = &uc->uc_path.cep_adds_vect;
2860
2861 /* Set the common primary address path fields */
2862 status = hermon_set_addr_path(state, adds_vect,
2863 qpc_path, HERMON_ADDRPATH_QP);
2864 if (status != DDI_SUCCESS) {
2865 return (status);
2866 }
2867 portnum = qp->qp_portnum + 1;
2868 if (hermon_portnum_is_valid(state, portnum)) {
2869 qpc->pri_addr_path.sched_q =
2870 HERMON_QP_SCHEDQ_GET(qp->qp_portnum,
2871 adds_vect->av_srvl, qp->qp_is_special);
2872 } else {
2873 return (IBT_HCA_PORT_INVALID);
2874 }
2875
2876 /*
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.
2880 */
2881 qpc->mtu = qp->qp_save_mtu;
2882
2883 opmask |= HERMON_CMD_OP_PRIM_PATH;
2884 }
2885
2886 /*
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.
2890 */
2891 if (flags & IBT_CEP_SET_MIG) {
2892 if (uc->uc_mig_state == IBT_STATE_MIGRATED) {
2893 qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
2894 } else if (uc->uc_mig_state == IBT_STATE_REARMED) {
2895 qpc->pm_state = HERMON_QP_PMSTATE_REARM;
2896 } else {
2897 return (IBT_QP_APM_STATE_INVALID);
2898 }
2899 opmask |= HERMON_CMD_OP_PM_STATE;
2900 }
2901
2902 /*
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.
2906 */
2907 if (flags & IBT_CEP_SET_PKEY_IX) {
2908 pkeyindx = uc->uc_path.cep_pkey_ix;
2909 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
2910 qpc->pri_addr_path.pkey_indx = pkeyindx;
2911 opmask |= HERMON_CMD_OP_PKEYINDX;
2912 } else {
2913 return (IBT_PKEY_IX_ILLEGAL);
2914 }
2915 }
2916
2917 /*
2918 * Check for optional alternate path and fill in the
2919 * appropriate QPC fields if one is specified
2920 */
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;
2924
2925 /* Set the common alternate address path fields */
2926 status = hermon_set_addr_path(state, adds_vect,
2927 qpc_path, HERMON_ADDRPATH_QP);
2928 if (status != DDI_SUCCESS) {
2929 return (status);
2930 }
2931
2932 /*
2933 * Check for valid alternate path port number and fill
2934 * it in
2935 */
2936 portnum = uc->uc_alt_path.cep_hca_port_num;
2937 if (hermon_portnum_is_valid(state, portnum)) {
2938 qp->qp_portnum_alt = portnum - 1;
2939 qpc->alt_addr_path.sched_q =
2940 HERMON_QP_SCHEDQ_GET(portnum - 1,
2941 adds_vect->av_srvl, qp->qp_is_special);
2942 } else {
2943 return (IBT_HCA_PORT_INVALID);
2944 }
2945
2946 /*
2947 * Check for valid alternate path PKey index and fill
2948 * it in
2949 */
2950 pkeyindx = uc->uc_alt_path.cep_pkey_ix;
2951 if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
2952 qpc->alt_addr_path.pkey_indx = pkeyindx;
2953 } else {
2954 return (IBT_PKEY_IX_ILLEGAL);
2955 }
2956 opmask |= HERMON_CMD_OP_ALT_PATH;
2957 }
2958 } else {
2959 /*
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
2963 */
2964 HERMON_WARNING(state, "unknown QP transport type in sqd2sqd");
2965 return (ibc_get_ci_failure(0));
2966 }
2967
2968 /*
2969 * Post the SQD2SQD_QP command to the Hermon firmware
2970 *
2971 * We do a HERMON_NOSLEEP here because we are still holding the
2972 * "qp_lock". If we got raised to interrupt level by priority
2973 * inversion, we do not want to block in this routine waiting for
2974 * success.
2975 */
2976 status = hermon_cmn_qp_cmd_post(state, SQD2SQD_QP, qpc, qp->qp_qpnum,
2977 opmask, HERMON_CMD_NOSLEEP_SPIN);
2978 if (status != HERMON_CMD_SUCCESS) {
2979 if (status != HERMON_CMD_BAD_QP_STATE) {
2980 cmn_err(CE_NOTE, "hermon%d: SQD2SQD_QP command failed: "
2981 "%08x\n", state->hs_instance, status);
2982 if (status == HERMON_CMD_INVALID_STATUS) {
2983 hermon_fm_ereport(state, HCA_SYS_ERR,
2984 HCA_ERR_SRV_LOST);
2985 }
2986 return (ibc_get_ci_failure(0));
2987 } else {
2988 return (IBT_QP_STATE_INVALID);
2989 }
2990 }
2991
2992 return (DDI_SUCCESS);
2993 }
2994
2995
2996 /*
2997 * hermon_qp_sqerr2rts()
2998 * Context: Can be called from interrupt or base context.
2999 */
3000 static int
hermon_qp_sqerr2rts(hermon_state_t * state,hermon_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p)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)
3003 {
3004 hermon_hw_qpc_t *qpc;
3005 ibt_qp_ud_attr_t *ud;
3006 uint32_t opmask = 0;
3007 int status;
3008
3009 ASSERT(MUTEX_HELD(&qp->qp_lock));
3010
3011 /*
3012 * Grab the temporary QPC entry from QP software state
3013 */
3014 qpc = &qp->qpc;
3015
3016 /*
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.
3019 */
3020 if (qp->qp_type == IBT_UD_RQP) {
3021 ud = &info_p->qp_transport.ud;
3022
3023 /*
3024 * If we are attempting to modify the QKey for this QP, then
3025 * fill it in and set the appropriate flag in the "opmask"
3026 * parameter.
3027 */
3028 if (flags & IBT_CEP_SET_QKEY) {
3029 qpc->qkey = ud->ud_qkey;
3030 opmask |= HERMON_CMD_OP_QKEY;
3031 }
3032
3033 } else if (qp->qp_serv_type == HERMON_QP_UC) {
3034
3035 /*
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.
3040 */
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;
3044 }
3045 } else {
3046 /*
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
3050 */
3051 HERMON_WARNING(state, "unknown QP transport type in sqerr2rts");
3052 return (ibc_get_ci_failure(0));
3053 }
3054
3055 /*
3056 * Post the SQERR2RTS_QP command to the Hermon firmware
3057 *
3058 * We do a HERMON_NOSLEEP here because we are still holding the
3059 * "qp_lock". If we got raised to interrupt level by priority
3060 * inversion, we do not want to block in this routine waiting for
3061 * success.
3062 */
3063 status = hermon_cmn_qp_cmd_post(state, SQERR2RTS_QP, qpc, qp->qp_qpnum,
3064 opmask, HERMON_CMD_NOSLEEP_SPIN);
3065 if (status != HERMON_CMD_SUCCESS) {
3066 if (status != HERMON_CMD_BAD_QP_STATE) {
3067 cmn_err(CE_NOTE, "hermon%d: SQERR2RTS_QP command "
3068 "failed: %08x\n", state->hs_instance, status);
3069 if (status == HERMON_CMD_INVALID_STATUS) {
3070 hermon_fm_ereport(state, HCA_SYS_ERR,
3071 HCA_ERR_SRV_LOST);
3072 }
3073 return (ibc_get_ci_failure(0));
3074 } else {
3075 return (IBT_QP_STATE_INVALID);
3076 }
3077 }
3078
3079 return (DDI_SUCCESS);
3080 }
3081
3082
3083 /*
3084 * hermon_qp_to_error()
3085 * Context: Can be called from interrupt or base context.
3086 */
3087 static int
hermon_qp_to_error(hermon_state_t * state,hermon_qphdl_t qp)3088 hermon_qp_to_error(hermon_state_t *state, hermon_qphdl_t qp)
3089 {
3090 int status;
3091
3092 ASSERT(MUTEX_HELD(&qp->qp_lock));
3093
3094 /*
3095 * Post the TOERR_QP command to the Hermon firmware
3096 *
3097 * We do a HERMON_NOSLEEP here because we are still holding the
3098 * "qp_lock". If we got raised to interrupt level by priority
3099 * inversion, we do not want to block in this routine waiting for
3100 * success.
3101 */
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);
3109 }
3110 return (ibc_get_ci_failure(0));
3111 }
3112
3113 return (DDI_SUCCESS);
3114 }
3115
3116
3117 /*
3118 * hermon_qp_to_reset()
3119 * Context: Can be called from interrupt or base context.
3120 */
3121 int
hermon_qp_to_reset(hermon_state_t * state,hermon_qphdl_t qp)3122 hermon_qp_to_reset(hermon_state_t *state, hermon_qphdl_t qp)
3123 {
3124 hermon_hw_qpc_t *qpc;
3125 int status;
3126
3127 ASSERT(MUTEX_HELD(&qp->qp_lock));
3128
3129 /*
3130 * Grab the temporary QPC entry from QP software state
3131 */
3132 qpc = &qp->qpc;
3133
3134 /*
3135 * Post the TORST_QP command to the Hermon firmware
3136 *
3137 * We do a HERMON_NOSLEEP here because we are still holding the
3138 * "qp_lock". If we got raised to interrupt level by priority
3139 * inversion, we do not want to block in this routine waiting for
3140 * success.
3141 */
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);
3149 }
3150 return (ibc_get_ci_failure(0));
3151 }
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);
3158 }
3159 return (DDI_SUCCESS);
3160 }
3161
3162
3163 /*
3164 * hermon_qp_reset2err()
3165 * Context: Can be called from interrupt or base context.
3166 */
3167 static int
hermon_qp_reset2err(hermon_state_t * state,hermon_qphdl_t qp)3168 hermon_qp_reset2err(hermon_state_t *state, hermon_qphdl_t qp)
3169 {
3170 hermon_hw_qpc_t *qpc;
3171 int status;
3172 uint32_t cqnmask;
3173
3174 ASSERT(MUTEX_HELD(&qp->qp_lock));
3175
3176 /*
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".
3182 *
3183 * When this function returns success, the QP context will be owned by
3184 * the Hermon hardware and will be in the "Error" state.
3185 */
3186
3187 /*
3188 * Grab the temporary QPC entry from QP software state
3189 */
3190 qpc = &qp->qpc;
3191
3192 /*
3193 * Fill in the common fields in the QPC
3194 */
3195 if (qp->qp_is_special) {
3196 qpc->serv_type = HERMON_QP_MLX;
3197 } else {
3198 qpc->serv_type = qp->qp_serv_type;
3199 }
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;
3206 /*
3207 * HERMON:
3208 * qpc->wqe_baseaddr is replaced by LKey from the cMPT, and
3209 * page_offset, mtt_base_addr_h/l, and log2_page_size will
3210 * be used to map the WQE buffer
3211 * NOTE that the cMPT is created implicitly when the QP is
3212 * transitioned from reset to init
3213 */
3214 qpc->log2_pgsz = qp->qp_mrhdl->mr_log2_pgsz;
3215 qpc->mtt_base_addrh = (qp->qp_mrhdl->mr_mttaddr) >> 32 & 0xFF;
3216 qpc->mtt_base_addrl = (qp->qp_mrhdl->mr_mttaddr) >> 3 & 0xFFFFFFFF;
3217 cqnmask = (1 << state->hs_cfg_profile->cp_log_num_cq) - 1;
3218 qpc->cqn_snd =
3219 (qp->qp_sq_cqhdl == NULL) ? 0 : qp->qp_sq_cqhdl->cq_cqnum & cqnmask;
3220 qpc->page_offs = qp->qp_wqinfo.qa_pgoffs >> 6;
3221 qpc->cqn_rcv =
3222 (qp->qp_rq_cqhdl == NULL) ? 0 : qp->qp_rq_cqhdl->cq_cqnum & cqnmask;
3223
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;
3232
3233 if (qp->qp_alloc_flags & IBT_QP_USES_SRQ) {
3234 qpc->srq_number = qp->qp_srqhdl->srq_srqnum;
3235 } else {
3236 qpc->srq_number = 0;
3237 }
3238
3239 qpc->fre = 0; /* default disable fast registration WR */
3240 qpc->rlky = 0; /* default disable reserved lkey */
3241
3242 /*
3243 * Now fill in the QPC fields which are specific to transport type
3244 */
3245 if (qp->qp_type == IBT_UD_RQP) {
3246 /* Set the UD parameters to an invalid default */
3247 qpc->qkey = 0;
3248 qpc->pri_addr_path.sched_q =
3249 HERMON_QP_SCHEDQ_GET(0, 0, qp->qp_is_special);
3250 qpc->pri_addr_path.pkey_indx = 0;
3251
3252 } else if (qp->qp_serv_type == HERMON_QP_RC) {
3253 /* Set the RC parameters to invalid default */
3254 qpc->rre = 0;
3255 qpc->rwe = 0;
3256 qpc->rae = 0;
3257 qpc->alt_addr_path.sched_q =
3258 HERMON_QP_SCHEDQ_GET(0, 0, qp->qp_is_special);
3259 qpc->pri_addr_path.pkey_indx = 0;
3260
3261 } else if (qp->qp_serv_type == HERMON_QP_UC) {
3262 /* Set the UC parameters to invalid default */
3263 qpc->rwe = 0;
3264 qpc->alt_addr_path.sched_q =
3265 HERMON_QP_SCHEDQ_GET(0, 0, qp->qp_is_special);
3266 qpc->pri_addr_path.pkey_indx = 0;
3267
3268 } else {
3269 /*
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
3273 */
3274 HERMON_WARNING(state, "unknown QP transport type in rst2err");
3275 return (ibc_get_ci_failure(0));
3276 }
3277
3278 /*
3279 * Post the RST2INIT_QP command to the Hermon firmware
3280 *
3281 * We do a HERMON_NOSLEEP here because we are still holding the
3282 * "qp_lock". If we got raised to interrupt level by priority
3283 * inversion, we do not want to block in this routine waiting for
3284 * success.
3285 */
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);
3293 }
3294 return (ibc_get_ci_failure(0));
3295 }
3296
3297 /*
3298 * Now post the TOERR_QP command to the Hermon firmware
3299 *
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.
3305 */
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);
3313 }
3314 if (hermon_qp_to_reset(state, qp) != DDI_SUCCESS) {
3315 HERMON_WARNING(state, "failed to reset QP context");
3316 }
3317 return (ibc_get_ci_failure(0));
3318 }
3319
3320 return (DDI_SUCCESS);
3321 }
3322
3323
3324 /*
3325 * hermon_check_rdma_enable_flags()
3326 * Context: Can be called from interrupt or base context.
3327 */
3328 static uint_t
hermon_check_rdma_enable_flags(ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p,hermon_hw_qpc_t * qpc)3329 hermon_check_rdma_enable_flags(ibt_cep_modify_flags_t flags,
3330 ibt_qp_info_t *info_p, hermon_hw_qpc_t *qpc)
3331 {
3332 uint_t opmask = 0;
3333
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;
3337 }
3338
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;
3342 }
3343
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;
3347 }
3348
3349 return (opmask);
3350 }
3351
3352 /*
3353 * hermon_qp_validate_resp_rsrc()
3354 * Context: Can be called from interrupt or base context.
3355 */
3356 static int
hermon_qp_validate_resp_rsrc(hermon_state_t * state,ibt_qp_rc_attr_t * rc,uint_t * rra_max)3357 hermon_qp_validate_resp_rsrc(hermon_state_t *state, ibt_qp_rc_attr_t *rc,
3358 uint_t *rra_max)
3359 {
3360 uint_t rdma_ra_in;
3361
3362 rdma_ra_in = rc->rc_rdma_ra_in;
3363
3364 /*
3365 * Check if number of responder resources is too large. Return an
3366 * error if it is
3367 */
3368 if (rdma_ra_in > state->hs_cfg_profile->cp_hca_max_rdma_in_qp) {
3369 return (IBT_INVALID_PARAM);
3370 }
3371
3372 /*
3373 * If the number of responder resources is too small, round it up.
3374 * Then find the next highest power-of-2
3375 */
3376 if (rdma_ra_in == 0) {
3377 rdma_ra_in = 1;
3378 }
3379 if (ISP2(rdma_ra_in)) {
3380 *rra_max = highbit(rdma_ra_in) - 1;
3381 } else {
3382 *rra_max = highbit(rdma_ra_in);
3383 }
3384 return (DDI_SUCCESS);
3385 }
3386
3387
3388 /*
3389 * hermon_qp_validate_init_depth()
3390 * Context: Can be called from interrupt or base context.
3391 */
3392 static int
hermon_qp_validate_init_depth(hermon_state_t * state,ibt_qp_rc_attr_t * rc,uint_t * sra_max)3393 hermon_qp_validate_init_depth(hermon_state_t *state, ibt_qp_rc_attr_t *rc,
3394 uint_t *sra_max)
3395 {
3396 uint_t rdma_ra_out;
3397
3398 rdma_ra_out = rc->rc_rdma_ra_out;
3399
3400 /*
3401 * Check if requested initiator depth is too large. Return an error
3402 * if it is
3403 */
3404 if (rdma_ra_out > state->hs_cfg_profile->cp_hca_max_rdma_out_qp) {
3405 return (IBT_INVALID_PARAM);
3406 }
3407
3408 /*
3409 * If the requested initiator depth is too small, round it up.
3410 * Then find the next highest power-of-2
3411 */
3412 if (rdma_ra_out == 0) {
3413 rdma_ra_out = 1;
3414 }
3415 if (ISP2(rdma_ra_out)) {
3416 *sra_max = highbit(rdma_ra_out) - 1;
3417 } else {
3418 *sra_max = highbit(rdma_ra_out);
3419 }
3420 return (DDI_SUCCESS);
3421 }
3422
3423
3424 /*
3425 * hermon_qp_validate_mtu()
3426 * Context: Can be called from interrupt or base context.
3427 */
3428 static int
hermon_qp_validate_mtu(hermon_state_t * state,uint_t mtu)3429 hermon_qp_validate_mtu(hermon_state_t *state, uint_t mtu)
3430 {
3431 /*
3432 * Check for invalid MTU values (i.e. zero or any value larger than
3433 * the HCA's port maximum).
3434 */
3435 if ((mtu == 0) || (mtu > state->hs_cfg_profile->cp_max_mtu)) {
3436 return (IBT_HCA_PORT_MTU_EXCEEDED);
3437 }
3438 return (DDI_SUCCESS);
3439 }
3440