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