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
46static int tavor_qp_reset2init(tavor_state_t *state, tavor_qphdl_t qp,
47    ibt_qp_info_t *info_p);
48static 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);
50static 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);
52static 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);
54static 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);
56static int tavor_qp_rts2sqd(tavor_state_t *state, tavor_qphdl_t qp,
57    ibt_cep_modify_flags_t flags);
58static 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);
60static 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);
62static 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);
64static int tavor_qp_to_error(tavor_state_t *state, tavor_qphdl_t qp);
65static int tavor_qp_reset2err(tavor_state_t *state, tavor_qphdl_t qp);
66
67static 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);
69static int tavor_qp_validate_resp_rsrc(tavor_state_t *state,
70    ibt_qp_rc_attr_t *rc, uint_t *rra_max);
71static int tavor_qp_validate_init_depth(tavor_state_t *state,
72    ibt_qp_rc_attr_t *rc, uint_t *sra_max);
73static 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 */
80int
81tavor_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
836qpmod_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 */
848static int
849tavor_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 */
1032static int
1033tavor_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 */
1257static int
1258tavor_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 */
1680static int
1681tavor_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 */
2006static int
2007tavor_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 */
2269static int
2270tavor_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 */
2330static int
2331tavor_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 */
2593static int
2594tavor_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 */
3070static int
3071tavor_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 */
3166static int
3167tavor_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 */
3203int
3204tavor_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 */
3246static int
3247tavor_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 */
3390static uint_t
3391tavor_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 */
3418static int
3419tavor_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 */
3454static int
3455tavor_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 */
3490static int
3491tavor_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