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