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