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