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