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