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