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