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