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