Print this page
8368 remove warlock leftovers from usr/src/uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/ib/adapters/tavor/tavor_cmd.c
+++ new/usr/src/uts/common/io/ib/adapters/tavor/tavor_cmd.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 */
26 26
27 27 /*
28 28 * tavor_cmd.c
29 29 * Tavor Firmware Command Routines
30 30 *
31 31 * Implements all the routines necessary for allocating, posting, and
32 32 * freeing commands for the Tavor firmware. These routines manage a
33 33 * preallocated list of command mailboxes and provide interfaces to post
34 34 * each of the several dozen commands to the Tavor firmware.
35 35 */
36 36
37 37 #include <sys/types.h>
38 38 #include <sys/conf.h>
39 39 #include <sys/ddi.h>
40 40 #include <sys/sunddi.h>
41 41 #include <sys/modctl.h>
42 42
43 43 #include <sys/ib/adapters/tavor/tavor.h>
44 44
45 45 static int tavor_impl_mbox_alloc(tavor_state_t *state, tavor_mboxlist_t *mblist,
46 46 tavor_mbox_t **mb, uint_t mbox_wait);
47 47 static void tavor_impl_mbox_free(tavor_mboxlist_t *mblist, tavor_mbox_t **mb);
48 48 static int tavor_impl_mboxlist_init(tavor_state_t *state,
49 49 tavor_mboxlist_t *mblist, uint_t num_mbox, tavor_rsrc_type_t type);
50 50 static void tavor_impl_mboxlist_fini(tavor_state_t *state,
51 51 tavor_mboxlist_t *mblist);
52 52 static int tavor_outstanding_cmd_alloc(tavor_state_t *state,
53 53 tavor_cmd_t **cmd_ptr, uint_t cmd_wait);
54 54 static void tavor_outstanding_cmd_free(tavor_state_t *state,
55 55 tavor_cmd_t **cmd_ptr);
56 56 static int tavor_write_hcr(tavor_state_t *state, tavor_cmd_post_t *cmdpost,
57 57 uint16_t token);
58 58 static void tavor_mbox_sync(tavor_mbox_t *mbox, uint_t offset,
59 59 uint_t length, uint_t flag);
60 60
61 61 /*
62 62 * tavor_cmd_post()
63 63 * Context: Can be called from interrupt or base context.
64 64 *
65 65 * The "cp_flags" field in cmdpost
66 66 * is used to determine whether to wait for an available
67 67 * outstanding command (if necessary) or to return error.
↓ open down ↓ |
67 lines elided |
↑ open up ↑ |
68 68 */
69 69 int
70 70 tavor_cmd_post(tavor_state_t *state, tavor_cmd_post_t *cmdpost)
71 71 {
72 72 tavor_cmd_t *cmdptr;
73 73 int status;
74 74 uint16_t token;
75 75
76 76 TAVOR_TNF_ENTER(tavor_cmd_post);
77 77
78 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cmdpost))
79 -
80 78 /* Determine if we are going to spin until completion */
81 79 if (cmdpost->cp_flags == TAVOR_CMD_NOSLEEP_SPIN) {
82 80
83 81 TNF_PROBE_0_DEBUG(tavor_cmd_post_spin, TAVOR_TNF_TRACE, "");
84 82
85 83 /* Write the command to the HCR */
86 84 status = tavor_write_hcr(state, cmdpost, 0);
87 85 if (status != TAVOR_CMD_SUCCESS) {
88 86 TNF_PROBE_0(tavor_cmd_post_fail,
89 87 TAVOR_TNF_ERROR, "");
90 88 TAVOR_TNF_EXIT(tavor_cmd_post);
91 89 return (status);
92 90 }
93 91
94 92 TAVOR_TNF_EXIT(tavor_cmd_post);
95 93 return (TAVOR_CMD_SUCCESS);
96 94
97 95 } else { /* "TAVOR_CMD_SLEEP_NOSPIN" */
98 96
99 97 TNF_PROBE_0_DEBUG(tavor_cmd_post_nospin, TAVOR_TNF_TRACE, "");
100 98
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
101 99 ASSERT(TAVOR_SLEEPFLAG_FOR_CONTEXT() != TAVOR_NOSLEEP);
102 100
103 101 /* NOTE: Expect threads to be waiting in here */
104 102 status = tavor_outstanding_cmd_alloc(state, &cmdptr,
105 103 cmdpost->cp_flags);
106 104 if (status != TAVOR_CMD_SUCCESS) {
107 105 TNF_PROBE_0(tavor_cmd_alloc_fail, TAVOR_TNF_ERROR, "");
108 106 TAVOR_TNF_EXIT(tavor_cmd_post);
109 107 return (status);
110 108 }
111 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cmdptr))
112 109
113 110 /*
114 111 * Set status to "TAVOR_CMD_INVALID_STATUS". It is
115 112 * appropriate to do this here without the "cmd_comp_lock"
116 113 * because this register is overloaded. Later it will be
117 114 * used to indicate - through a change from this invalid
118 115 * value to some other value - that the condition variable
119 116 * has been signaled. Once it has, status will then contain
120 117 * the _real_ completion status
121 118 */
122 119 cmdptr->cmd_status = TAVOR_CMD_INVALID_STATUS;
123 120
124 121 /* Write the command to the HCR */
125 122 token = (uint16_t)cmdptr->cmd_indx;
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
126 123 status = tavor_write_hcr(state, cmdpost, token);
127 124 if (status != TAVOR_CMD_SUCCESS) {
128 125 tavor_outstanding_cmd_free(state, &cmdptr);
129 126 TNF_PROBE_0(tavor_cmd_post_fail, TAVOR_TNF_ERROR, "");
130 127 TAVOR_TNF_EXIT(tavor_cmd_post);
131 128 return (status);
132 129 }
133 130
134 131 /*
135 132 * cv_wait() on the "command_complete" condition variable.
136 - * Note: We have the "__lock_lint" here to workaround warlock.
137 - * Since warlock doesn't know that other parts of the Tavor
138 - * may occasionally call this routine while holding their own
139 - * locks, it complains about this cv_wait. In reality,
140 - * however, the rest of the driver never calls this routine
141 - * with a lock held unless they pass TAVOR_CMD_NOSLEEP.
142 133 */
143 - _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*cmdptr))
144 134 mutex_enter(&cmdptr->cmd_comp_lock);
145 135 while (cmdptr->cmd_status == TAVOR_CMD_INVALID_STATUS) {
146 -#ifndef __lock_lint
147 - cv_wait(&cmdptr->cmd_comp_cv, &cmdptr->cmd_comp_lock);
148 136 /* NOTE: EXPECT SEVERAL THREADS TO BE WAITING HERE */
149 -#endif
137 + cv_wait(&cmdptr->cmd_comp_cv, &cmdptr->cmd_comp_lock);
150 138 }
151 139 mutex_exit(&cmdptr->cmd_comp_lock);
152 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cmdptr))
153 140
154 141 /*
155 142 * Wake up after command completes (cv_signal). Read status
156 143 * from the command (success, fail, etc.). It is appropriate
157 144 * here (as above) to read the status field without the
158 145 * "cmd_comp_lock" because it is no longer being used to
159 146 * indicate whether the condition variable has been signaled
160 147 * (i.e. at this point we are certain that it already has).
161 148 */
162 149 status = cmdptr->cmd_status;
163 150
164 151 /* Save the "outparam" values into the cmdpost struct */
165 152 cmdpost->cp_outparm = cmdptr->cmd_outparm;
166 153
167 154 /*
168 155 * Add the command back to the "outstanding commands list".
169 156 * Signal the "cmd_list" condition variable, if necessary.
170 157 */
171 158 tavor_outstanding_cmd_free(state, &cmdptr);
172 159
173 160 if (status != TAVOR_CMD_SUCCESS) {
174 161 TNF_PROBE_0(tavor_cmd_post_fail, TAVOR_TNF_ERROR, "");
175 162 TAVOR_TNF_EXIT(tavor_cmd_post);
176 163 return (status);
177 164 }
178 165
179 166 TAVOR_TNF_EXIT(tavor_cmd_post);
180 167 return (TAVOR_CMD_SUCCESS);
181 168 }
182 169 }
183 170
184 171
185 172 /*
186 173 * tavor_mbox_alloc()
187 174 * Context: Can be called from interrupt or base context.
188 175 *
189 176 * The "mbox_wait" parameter is used to determine whether to
190 177 * wait for a mailbox to become available or not.
191 178 */
192 179 int
193 180 tavor_mbox_alloc(tavor_state_t *state, tavor_mbox_info_t *mbox_info,
194 181 uint_t mbox_wait)
195 182 {
196 183 int status;
197 184 uint_t sleep_context;
198 185
199 186 TAVOR_TNF_ENTER(tavor_mbox_alloc);
200 187
201 188 sleep_context = TAVOR_SLEEPFLAG_FOR_CONTEXT();
202 189
203 190 /* Allocate an "In" mailbox */
204 191 if (mbox_info->mbi_alloc_flags & TAVOR_ALLOC_INMBOX) {
205 192 /* Determine correct mboxlist based on calling context */
206 193 if (sleep_context == TAVOR_NOSLEEP) {
207 194 status = tavor_impl_mbox_alloc(state,
208 195 &state->ts_in_intr_mblist,
209 196 &mbox_info->mbi_in, mbox_wait);
210 197
211 198 ASSERT(status == TAVOR_CMD_SUCCESS);
212 199 } else {
213 200 /* NOTE: Expect threads to be waiting in here */
214 201 status = tavor_impl_mbox_alloc(state,
215 202 &state->ts_in_mblist, &mbox_info->mbi_in,
216 203 mbox_wait);
217 204 if (status != TAVOR_CMD_SUCCESS) {
218 205 TAVOR_TNF_EXIT(tavor_mbox_alloc);
219 206 return (status);
220 207 }
221 208 }
222 209
223 210 }
224 211
225 212 /* Allocate an "Out" mailbox */
226 213 if (mbox_info->mbi_alloc_flags & TAVOR_ALLOC_OUTMBOX) {
227 214 /* Determine correct mboxlist based on calling context */
228 215 if (sleep_context == TAVOR_NOSLEEP) {
229 216 status = tavor_impl_mbox_alloc(state,
230 217 &state->ts_out_intr_mblist,
231 218 &mbox_info->mbi_out, mbox_wait);
232 219
233 220 ASSERT(status == TAVOR_CMD_SUCCESS);
234 221 } else {
235 222 /* NOTE: Expect threads to be waiting in here */
236 223 status = tavor_impl_mbox_alloc(state,
237 224 &state->ts_out_mblist, &mbox_info->mbi_out,
238 225 mbox_wait);
239 226 if (status != TAVOR_CMD_SUCCESS) {
240 227 /* If we allocated an "In" mailbox, free it */
241 228 if (mbox_info->mbi_alloc_flags &
242 229 TAVOR_ALLOC_INMBOX) {
243 230 tavor_impl_mbox_free(
↓ open down ↓ |
81 lines elided |
↑ open up ↑ |
244 231 &state->ts_in_mblist,
245 232 &mbox_info->mbi_in);
246 233 }
247 234 TAVOR_TNF_EXIT(tavor_mbox_alloc);
248 235 return (status);
249 236 }
250 237 }
251 238 }
252 239
253 240 /* Store appropriate context in mbox_info */
254 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(mbox_info->mbi_sleep_context))
255 241 mbox_info->mbi_sleep_context = sleep_context;
256 242
257 243 TAVOR_TNF_EXIT(tavor_mbox_alloc);
258 244 return (TAVOR_CMD_SUCCESS);
259 245 }
260 246
261 247
262 248 /*
263 249 * tavor_mbox_free()
264 250 * Context: Can be called from interrupt or base context.
265 251 */
266 252 void
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
267 253 tavor_mbox_free(tavor_state_t *state, tavor_mbox_info_t *mbox_info)
268 254 {
269 255 TAVOR_TNF_ENTER(tavor_mbox_free);
270 256
271 257 /*
272 258 * The mailbox has to be freed in the same context from which it was
273 259 * allocated. The context is stored in the mbox_info at
274 260 * tavor_mbox_alloc() time. We check the stored context against the
275 261 * current context here.
276 262 */
277 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(mbox_info->mbi_sleep_context))
278 263 ASSERT(mbox_info->mbi_sleep_context == TAVOR_SLEEPFLAG_FOR_CONTEXT());
279 264
280 265 /* Determine correct mboxlist based on calling context */
281 266 if (mbox_info->mbi_sleep_context == TAVOR_NOSLEEP) {
282 267 /* Free the intr "In" mailbox */
283 268 if (mbox_info->mbi_alloc_flags & TAVOR_ALLOC_INMBOX) {
284 269 tavor_impl_mbox_free(&state->ts_in_intr_mblist,
285 270 &mbox_info->mbi_in);
286 271 }
287 272
288 273 /* Free the intr "Out" mailbox */
289 274 if (mbox_info->mbi_alloc_flags & TAVOR_ALLOC_OUTMBOX) {
290 275 tavor_impl_mbox_free(&state->ts_out_intr_mblist,
291 276 &mbox_info->mbi_out);
292 277 }
293 278 } else {
294 279 /* Free the "In" mailbox */
295 280 if (mbox_info->mbi_alloc_flags & TAVOR_ALLOC_INMBOX) {
296 281 tavor_impl_mbox_free(&state->ts_in_mblist,
297 282 &mbox_info->mbi_in);
298 283 }
299 284
300 285 /* Free the "Out" mailbox */
301 286 if (mbox_info->mbi_alloc_flags & TAVOR_ALLOC_OUTMBOX) {
302 287 tavor_impl_mbox_free(&state->ts_out_mblist,
303 288 &mbox_info->mbi_out);
304 289 }
305 290 }
306 291
307 292 TAVOR_TNF_EXIT(tavor_mbox_free);
308 293 }
309 294
310 295
311 296 /*
312 297 * tavor_cmd_complete_handler()
313 298 * Context: Called only from interrupt context.
314 299 */
315 300 int
316 301 tavor_cmd_complete_handler(tavor_state_t *state, tavor_eqhdl_t eq,
317 302 tavor_hw_eqe_t *eqe)
318 303 {
319 304 tavor_cmd_t *cmdp;
320 305 uint_t eqe_evttype;
321 306
322 307 TAVOR_TNF_ENTER(tavor_cmd_complete_handler);
323 308
324 309 eqe_evttype = TAVOR_EQE_EVTTYPE_GET(eq, eqe);
325 310
326 311 ASSERT(eqe_evttype == TAVOR_EVT_COMMAND_INTF_COMP ||
327 312 eqe_evttype == TAVOR_EVT_EQ_OVERFLOW);
328 313
329 314 if (eqe_evttype == TAVOR_EVT_EQ_OVERFLOW) {
330 315 TNF_PROBE_0(tavor_cmd_complete_overflow_condition,
331 316 TAVOR_TNF_ERROR, "");
332 317 tavor_eq_overflow_handler(state, eq, eqe);
333 318
334 319 TAVOR_TNF_EXIT(tavor_cmd_complete_handler);
335 320 return (DDI_FAILURE);
336 321 }
337 322
338 323 /*
339 324 * Find the outstanding command pointer based on value returned
340 325 * in "token"
341 326 */
342 327 cmdp = &state->ts_cmd_list.cml_cmd[TAVOR_EQE_CMDTOKEN_GET(eq, eqe)];
343 328
344 329 /* Signal the waiting thread */
345 330 mutex_enter(&cmdp->cmd_comp_lock);
346 331 cmdp->cmd_outparm = ((uint64_t)TAVOR_EQE_CMDOUTP0_GET(eq, eqe) << 32) |
347 332 TAVOR_EQE_CMDOUTP1_GET(eq, eqe);
348 333 cmdp->cmd_status = TAVOR_EQE_CMDSTATUS_GET(eq, eqe);
349 334
350 335 cv_signal(&cmdp->cmd_comp_cv);
351 336 mutex_exit(&cmdp->cmd_comp_lock);
352 337
353 338 TAVOR_TNF_EXIT(tavor_cmd_complete_handler);
354 339 return (DDI_SUCCESS);
355 340 }
356 341
357 342
358 343 /*
359 344 * tavor_inmbox_list_init()
360 345 * Context: Only called from attach() path context
361 346 */
362 347 int
363 348 tavor_inmbox_list_init(tavor_state_t *state)
364 349 {
365 350 int status;
366 351 uint_t num_inmbox;
367 352
368 353 TAVOR_TNF_ENTER(tavor_inmbox_list_init);
369 354
370 355 /* Initialize the "In" mailbox list */
371 356 num_inmbox = (1 << state->ts_cfg_profile->cp_log_num_inmbox);
372 357 status = tavor_impl_mboxlist_init(state, &state->ts_in_mblist,
373 358 num_inmbox, TAVOR_IN_MBOX);
374 359 if (status != DDI_SUCCESS) {
375 360 TNF_PROBE_0(tavor_impl_mboxlist_init_fail,
376 361 TAVOR_TNF_ERROR, "");
377 362 TAVOR_TNF_EXIT(tavor_inmbox_list_init);
378 363 return (DDI_FAILURE);
379 364 }
380 365
381 366 TAVOR_TNF_EXIT(tavor_inmbox_list_init);
382 367 return (DDI_SUCCESS);
383 368 }
384 369
385 370
386 371 /*
387 372 * tavor_intr_inmbox_list_init()
388 373 * Context: Only called from attach() path context
389 374 */
390 375 int
391 376 tavor_intr_inmbox_list_init(tavor_state_t *state)
392 377 {
393 378 int status;
394 379 uint_t num_inmbox;
395 380
396 381 TAVOR_TNF_ENTER(tavor_intr_inmbox_list_init);
397 382
398 383 /* Initialize the interrupt "In" mailbox list */
399 384 num_inmbox = (1 << state->ts_cfg_profile->cp_log_num_intr_inmbox);
400 385 status = tavor_impl_mboxlist_init(state, &state->ts_in_intr_mblist,
401 386 num_inmbox, TAVOR_INTR_IN_MBOX);
402 387 if (status != DDI_SUCCESS) {
403 388 TNF_PROBE_0(tavor_impl_mboxlist_init_fail,
404 389 TAVOR_TNF_ERROR, "");
405 390 TAVOR_TNF_EXIT(tavor_intr_inmbox_list_init);
406 391 return (DDI_FAILURE);
407 392 }
408 393
409 394 TAVOR_TNF_EXIT(tavor_intr_inmbox_list_init);
410 395 return (DDI_SUCCESS);
411 396 }
412 397
413 398
414 399 /*
415 400 * tavor_outmbox_list_init()
416 401 * Context: Only called from attach() path context
417 402 */
418 403 int
419 404 tavor_outmbox_list_init(tavor_state_t *state)
420 405 {
421 406 int status;
422 407 uint_t num_outmbox;
423 408
424 409 TAVOR_TNF_ENTER(tavor_outmbox_list_init);
425 410
426 411 /* Initialize the "Out" mailbox list */
427 412 num_outmbox = (1 << state->ts_cfg_profile->cp_log_num_outmbox);
428 413 status = tavor_impl_mboxlist_init(state, &state->ts_out_mblist,
429 414 num_outmbox, TAVOR_OUT_MBOX);
430 415 if (status != DDI_SUCCESS) {
431 416 TNF_PROBE_0(tavor_impl_mboxlist_init_fail,
432 417 TAVOR_TNF_ERROR, "");
433 418 TAVOR_TNF_EXIT(tavor_outmbox_list_init);
434 419 return (DDI_FAILURE);
435 420 }
436 421
437 422 TAVOR_TNF_EXIT(tavor_outmbox_list_init);
438 423 return (DDI_SUCCESS);
439 424 }
440 425
441 426
442 427 /*
443 428 * tavor_intr_outmbox_list_init()
444 429 * Context: Only called from attach() path context
445 430 */
446 431 int
447 432 tavor_intr_outmbox_list_init(tavor_state_t *state)
448 433 {
449 434 int status;
450 435 uint_t num_outmbox;
451 436
452 437 TAVOR_TNF_ENTER(tavor_intr_outmbox_list_init);
453 438
454 439 /* Initialize the interrupts "Out" mailbox list */
455 440 num_outmbox = (1 << state->ts_cfg_profile->cp_log_num_intr_outmbox);
456 441 status = tavor_impl_mboxlist_init(state, &state->ts_out_intr_mblist,
457 442 num_outmbox, TAVOR_INTR_OUT_MBOX);
458 443 if (status != DDI_SUCCESS) {
459 444 TNF_PROBE_0(tavor_impl_mboxlist_init_fail,
460 445 TAVOR_TNF_ERROR, "");
461 446 TAVOR_TNF_EXIT(tavor_intr_outmbox_list_init);
462 447 return (DDI_FAILURE);
463 448 }
464 449
465 450 TAVOR_TNF_EXIT(tavor_intr_outmbox_list_init);
466 451 return (DDI_SUCCESS);
467 452 }
468 453
469 454
470 455 /*
471 456 * tavor_inmbox_list_fini()
472 457 * Context: Only called from attach() and/or detach() path contexts
473 458 */
474 459 void
475 460 tavor_inmbox_list_fini(tavor_state_t *state)
476 461 {
477 462 TAVOR_TNF_ENTER(tavor_inmbox_list_fini);
478 463
479 464 /* Free up the "In" mailbox list */
480 465 tavor_impl_mboxlist_fini(state, &state->ts_in_mblist);
481 466
482 467 TAVOR_TNF_EXIT(tavor_inmbox_list_fini);
483 468 }
484 469
485 470
486 471 /*
487 472 * tavor_intr_inmbox_list_fini()
488 473 * Context: Only called from attach() and/or detach() path contexts
489 474 */
490 475 void
491 476 tavor_intr_inmbox_list_fini(tavor_state_t *state)
492 477 {
493 478 TAVOR_TNF_ENTER(tavor_intr_inmbox_list_fini);
494 479
495 480 /* Free up the interupts "In" mailbox list */
496 481 tavor_impl_mboxlist_fini(state, &state->ts_in_intr_mblist);
497 482
498 483 TAVOR_TNF_EXIT(tavor_intr_inmbox_list_fini);
499 484 }
500 485
501 486
502 487 /*
503 488 * tavor_outmbox_list_fini()
504 489 * Context: Only called from attach() and/or detach() path contexts
505 490 */
506 491 void
507 492 tavor_outmbox_list_fini(tavor_state_t *state)
508 493 {
509 494 TAVOR_TNF_ENTER(tavor_outmbox_list_fini);
510 495
511 496 /* Free up the "Out" mailbox list */
512 497 tavor_impl_mboxlist_fini(state, &state->ts_out_mblist);
513 498
514 499 TAVOR_TNF_EXIT(tavor_outmbox_list_fini);
515 500 }
516 501
517 502
518 503 /*
519 504 * tavor_intr_outmbox_list_fini()
520 505 * Context: Only called from attach() and/or detach() path contexts
521 506 */
522 507 void
523 508 tavor_intr_outmbox_list_fini(tavor_state_t *state)
524 509 {
525 510 TAVOR_TNF_ENTER(tavor_intr_outmbox_list_fini);
526 511
527 512 /* Free up the interrupt "Out" mailbox list */
528 513 tavor_impl_mboxlist_fini(state, &state->ts_out_intr_mblist);
529 514
530 515 TAVOR_TNF_EXIT(tavor_intr_outmbox_list_fini);
531 516 }
532 517
533 518
534 519 /*
535 520 * tavor_impl_mbox_alloc()
536 521 * Context: Can be called from interrupt or base context.
537 522 */
538 523 static int
539 524 tavor_impl_mbox_alloc(tavor_state_t *state, tavor_mboxlist_t *mblist,
540 525 tavor_mbox_t **mb, uint_t mbox_wait)
541 526 {
542 527 tavor_mbox_t *mbox_ptr;
543 528 uint_t index, next, prev;
544 529 uint_t count, countmax;
545 530
546 531 TAVOR_TNF_ENTER(tavor_impl_mbox_alloc);
547 532
548 533 /*
549 534 * If the mailbox list is empty, then wait (if appropriate in the
550 535 * current context). Otherwise, grab the next available mailbox.
551 536 */
552 537 if (mbox_wait == TAVOR_NOSLEEP) {
553 538 count = 0;
554 539 countmax = state->ts_cfg_profile->cp_cmd_poll_max;
555 540
556 541 mutex_enter(&mblist->mbl_lock);
557 542 mblist->mbl_pollers++;
558 543 while (mblist->mbl_entries_free == 0) {
559 544 mutex_exit(&mblist->mbl_lock);
560 545 /* Delay loop polling for an available mbox */
561 546 if (++count > countmax) {
562 547 TNF_PROBE_0(tavor_impl_mbox_alloc_fail,
563 548 TAVOR_TNF_ERROR, "");
564 549 TAVOR_TNF_EXIT(tavor_impl_mbox_alloc);
565 550 return (TAVOR_CMD_INSUFF_RSRC);
566 551 }
567 552
568 553 /* Delay before polling for mailbox again */
569 554 drv_usecwait(state->ts_cfg_profile->cp_cmd_poll_delay);
570 555 mutex_enter(&mblist->mbl_lock);
571 556 }
↓ open down ↓ |
284 lines elided |
↑ open up ↑ |
572 557 mblist->mbl_pollers--;
573 558
574 559 /* TAVOR_SLEEP */
575 560 } else {
576 561 /*
577 562 * Grab lock here as we prepare to cv_wait if needed.
578 563 */
579 564 mutex_enter(&mblist->mbl_lock);
580 565 while (mblist->mbl_entries_free == 0) {
581 566 /*
582 - * Wait (on cv) for a mailbox to become free. Note:
583 - * Just as we do above in tavor_cmd_post(), we also
584 - * have the "__lock_lint" here to workaround warlock.
585 - * Warlock doesn't know that other parts of the Tavor
586 - * may occasionally call this routine while holding
587 - * their own locks, so it complains about this cv_wait.
588 - * In reality, however, the rest of the driver never
589 - * calls this routine with a lock held unless they pass
590 - * TAVOR_CMD_NOSLEEP.
567 + * Wait (on cv) for a mailbox to become free.
591 568 */
592 569 mblist->mbl_waiters++;
593 -#ifndef __lock_lint
594 570 cv_wait(&mblist->mbl_cv, &mblist->mbl_lock);
595 -#endif
596 571 }
597 572 }
598 573
599 574 /* Grab the next available mailbox from list */
600 575 mbox_ptr = mblist->mbl_mbox;
601 576 index = mblist->mbl_head_indx;
602 577 next = mbox_ptr[index].mb_next;
603 578 prev = mbox_ptr[index].mb_prev;
604 579
605 580 /* Remove it from the mailbox list */
606 581 mblist->mbl_mbox[next].mb_prev = prev;
607 582 mblist->mbl_mbox[prev].mb_next = next;
608 583 mblist->mbl_head_indx = next;
609 584
610 585 /* Update the "free" count and return the mailbox pointer */
611 586 mblist->mbl_entries_free--;
612 587 *mb = &mbox_ptr[index];
613 588
614 589 mutex_exit(&mblist->mbl_lock);
615 590
616 591 TAVOR_TNF_EXIT(tavor_impl_mbox_alloc);
617 592 return (TAVOR_CMD_SUCCESS);
618 593 }
619 594
620 595
621 596 /*
622 597 * tavor_impl_mbox_free()
623 598 * Context: Can be called from interrupt or base context.
624 599 */
625 600 static void
626 601 tavor_impl_mbox_free(tavor_mboxlist_t *mblist, tavor_mbox_t **mb)
627 602 {
628 603 uint_t mbox_indx;
629 604
630 605 TAVOR_TNF_ENTER(tavor_impl_mbox_free);
631 606
632 607 mutex_enter(&mblist->mbl_lock);
633 608
634 609 /* Pull the "index" from mailbox entry */
635 610 mbox_indx = (*mb)->mb_indx;
636 611
637 612 /*
638 613 * If mailbox list is not empty, then insert the entry. Otherwise,
639 614 * this is the only entry. So update the pointers appropriately.
640 615 */
641 616 if (mblist->mbl_entries_free++ != 0) {
642 617 /* Update the current mailbox */
643 618 (*mb)->mb_next = mblist->mbl_head_indx;
644 619 (*mb)->mb_prev = mblist->mbl_tail_indx;
645 620
646 621 /* Update head and tail mailboxes */
647 622 mblist->mbl_mbox[mblist->mbl_head_indx].mb_prev = mbox_indx;
648 623 mblist->mbl_mbox[mblist->mbl_tail_indx].mb_next = mbox_indx;
649 624
650 625 /* Update tail index */
651 626 mblist->mbl_tail_indx = mbox_indx;
652 627
653 628 } else {
654 629 /* Update the current mailbox */
655 630 (*mb)->mb_next = mbox_indx;
656 631 (*mb)->mb_prev = mbox_indx;
657 632
658 633 /* Update head and tail indexes */
659 634 mblist->mbl_tail_indx = mbox_indx;
660 635 mblist->mbl_head_indx = mbox_indx;
661 636 }
662 637
663 638 /*
664 639 * Because we can have both waiters (SLEEP treads waiting for a
665 640 * cv_signal to continue processing) and pollers (NOSLEEP treads
666 641 * polling for a mailbox to become available), we try to share CPU time
667 642 * between them. We do this by signalling the waiters only every other
668 643 * call to mbox_free. This gives the pollers a chance to get some CPU
669 644 * time to do their command. If we signalled every time, the pollers
670 645 * would have a much harder time getting CPU time.
671 646 *
672 647 * If there are waiters and no pollers, then we signal always.
673 648 *
674 649 * Otherwise, if there are either no waiters, there may in fact be
675 650 * pollers, so we do not signal in that case.
676 651 */
677 652 if (mblist->mbl_pollers > 0 && mblist->mbl_waiters > 0) {
678 653 /* flip the signal value */
679 654 mblist->mbl_signal = (mblist->mbl_signal + 1) % 2;
680 655 } else if (mblist->mbl_waiters > 0) {
681 656 mblist->mbl_signal = 1;
682 657 } else {
683 658 mblist->mbl_signal = 0;
684 659 }
685 660
686 661 /*
687 662 * Depending on the conditions in the previous check, we signal only if
688 663 * we are supposed to.
689 664 */
690 665 if (mblist->mbl_signal) {
691 666 mblist->mbl_waiters--;
692 667 cv_signal(&mblist->mbl_cv);
693 668 }
694 669
695 670 /* Clear out the mailbox entry pointer */
696 671 *mb = NULL;
697 672
698 673 mutex_exit(&mblist->mbl_lock);
699 674
700 675 TAVOR_TNF_EXIT(tavor_impl_mbox_free);
701 676 }
702 677
703 678
704 679 /*
705 680 * tavor_impl_mboxlist_init()
706 681 * Context: Only called from attach() path context
707 682 */
708 683 static int
709 684 tavor_impl_mboxlist_init(tavor_state_t *state, tavor_mboxlist_t *mblist,
710 685 uint_t num_mbox, tavor_rsrc_type_t type)
711 686 {
712 687 tavor_rsrc_t *rsrc;
713 688 ddi_dma_cookie_t dma_cookie;
714 689 uint_t dma_cookiecnt, flag, sync;
715 690 int status, i;
716 691
717 692 TAVOR_TNF_ENTER(tavor_impl_mboxlist_init);
718 693
719 694 /* Allocate the memory for the mailbox entries list */
720 695 mblist->mbl_list_sz = num_mbox;
721 696 mblist->mbl_mbox = kmem_zalloc(mblist->mbl_list_sz *
722 697 sizeof (tavor_mbox_t), KM_SLEEP);
723 698
724 699 /* Initialize the mailbox entries list */
725 700 mblist->mbl_head_indx = 0;
726 701 mblist->mbl_tail_indx = mblist->mbl_list_sz - 1;
727 702 mblist->mbl_entries_free = mblist->mbl_list_sz;
728 703 mblist->mbl_waiters = 0;
729 704 mblist->mbl_num_alloc = 0;
730 705
731 706 /* Set up the mailbox list's cv and mutex */
732 707 mutex_init(&mblist->mbl_lock, NULL, MUTEX_DRIVER,
733 708 DDI_INTR_PRI(state->ts_intrmsi_pri));
734 709 cv_init(&mblist->mbl_cv, NULL, CV_DRIVER, NULL);
735 710
736 711 /* Determine if syncs will be necessary */
737 712 sync = TAVOR_MBOX_IS_SYNC_REQ(state, type);
738 713
739 714 /* Determine whether to map DDI_DMA_STREAMING or DDI_DMA_CONSISTENT */
740 715 flag = state->ts_cfg_profile->cp_streaming_consistent;
741 716
742 717 /* Initialize the mailbox list entries */
743 718 for (i = 0; i < mblist->mbl_list_sz; i++) {
744 719 /* Allocate resources for the mailbox */
745 720 status = tavor_rsrc_alloc(state, type, 1, TAVOR_SLEEP,
746 721 &rsrc);
747 722 if (status != DDI_SUCCESS) {
748 723 /* Jump to cleanup and return error */
749 724 TNF_PROBE_0(tavor_impl_mbox_init_rsrcalloc_fail,
750 725 TAVOR_TNF_ERROR, "");
751 726 goto mboxlist_init_fail;
752 727 }
753 728
754 729 /* Save away the mailbox resource info */
755 730 mblist->mbl_mbox[i].mb_rsrcptr = rsrc;
756 731 mblist->mbl_mbox[i].mb_addr = rsrc->tr_addr;
757 732 mblist->mbl_mbox[i].mb_acchdl = rsrc->tr_acchdl;
758 733
759 734 /*
760 735 * Get a PCI mapped address for each mailbox. Note: this
761 736 * uses the ddi_dma_handle return from the resource
762 737 * allocation routine
763 738 */
764 739 status = ddi_dma_addr_bind_handle(rsrc->tr_dmahdl, NULL,
765 740 rsrc->tr_addr, rsrc->tr_len, (DDI_DMA_RDWR | flag),
766 741 DDI_DMA_SLEEP, NULL, &dma_cookie, &dma_cookiecnt);
767 742 if (status != DDI_SUCCESS) {
768 743 /* Jump to cleanup and return error */
769 744 tavor_rsrc_free(state, &rsrc);
770 745 TNF_PROBE_0(tavor_impl_mbox_init_dmabind_fail,
771 746 TAVOR_TNF_ERROR, "");
772 747 goto mboxlist_init_fail;
773 748 }
774 749
775 750 /* Save away the mapped address for the mailbox */
776 751 mblist->mbl_mbox[i].mb_mapaddr = dma_cookie.dmac_laddress;
777 752
778 753 /* Set sync flag appropriately */
779 754 mblist->mbl_mbox[i].mb_sync = sync;
780 755
781 756 /* Make each entry point to the "next" and "prev" entries */
782 757 mblist->mbl_mbox[i].mb_next = i+1;
783 758 mblist->mbl_mbox[i].mb_prev = i-1;
784 759 mblist->mbl_mbox[i].mb_indx = i;
785 760 mblist->mbl_num_alloc = i + 1;
786 761 }
787 762
788 763 /* Make the "head" and "tail" entries point to each other */
789 764 mblist->mbl_mbox[mblist->mbl_head_indx].mb_prev =
790 765 mblist->mbl_tail_indx;
791 766 mblist->mbl_mbox[mblist->mbl_tail_indx].mb_next =
792 767 mblist->mbl_head_indx;
793 768
794 769 TAVOR_TNF_EXIT(tavor_impl_mboxlist_init);
795 770 return (DDI_SUCCESS);
796 771
797 772 mboxlist_init_fail:
798 773 tavor_impl_mboxlist_fini(state, mblist);
799 774
800 775 TAVOR_TNF_EXIT(tavor_impl_mboxlist_init);
801 776 return (DDI_FAILURE);
802 777 }
803 778
804 779
805 780 /*
806 781 * tavor_impl_mboxlist_fini()
807 782 * Context: Only called from attach() and/or detach() path contexts
808 783 */
809 784 static void
810 785 tavor_impl_mboxlist_fini(tavor_state_t *state, tavor_mboxlist_t *mblist)
811 786 {
812 787 tavor_rsrc_t *rsrc;
813 788 int i, status;
814 789
815 790 TAVOR_TNF_ENTER(tavor_impl_mboxlist_fini);
816 791
817 792 /* Release the resources for each of the mailbox list entries */
818 793 for (i = 0; i < mblist->mbl_num_alloc; i++) {
819 794 rsrc = mblist->mbl_mbox[i].mb_rsrcptr;
820 795
821 796 /*
822 797 * First, unbind the DMA memory for the mailbox
823 798 *
824 799 * Note: The only way ddi_dma_unbind_handle() currently
825 800 * can return an error is if the handle passed in is invalid.
826 801 * Since this should never happen, we choose to return void
827 802 * from this function! If this does return an error,
828 803 * however, then we print a warning message to the console.
829 804 */
830 805 status = ddi_dma_unbind_handle(rsrc->tr_dmahdl);
831 806 if (status != DDI_SUCCESS) {
832 807 TAVOR_WARNING(state, "failed to unbind DMA mapping");
833 808 TNF_PROBE_0(tavor_impl_mboxlist_fini_dmaunbind_fail,
834 809 TAVOR_TNF_ERROR, "");
835 810 TAVOR_TNF_EXIT(tavor_impl_mboxlist_fini);
836 811 return;
837 812 }
838 813
839 814 /* Next, free the mailbox resource */
840 815 tavor_rsrc_free(state, &rsrc);
841 816 }
842 817
843 818 /* Destroy the mailbox list mutex and cv */
844 819 mutex_destroy(&mblist->mbl_lock);
845 820 cv_destroy(&mblist->mbl_cv);
846 821
847 822 /* Free up the memory for tracking the mailbox list */
848 823 kmem_free(mblist->mbl_mbox, mblist->mbl_list_sz *
849 824 sizeof (tavor_mbox_t));
850 825
851 826 TAVOR_TNF_EXIT(tavor_impl_mboxlist_fini);
852 827 }
853 828
854 829
855 830 /*
856 831 * tavor_outstanding_cmd_alloc()
857 832 * Context: Can be called only from base context.
858 833 */
859 834 static int
860 835 tavor_outstanding_cmd_alloc(tavor_state_t *state, tavor_cmd_t **cmd_ptr,
861 836 uint_t cmd_wait)
862 837 {
863 838 tavor_cmdlist_t *cmd_list;
864 839 uint_t next, prev, head;
865 840
866 841 TAVOR_TNF_ENTER(tavor_outstanding_cmd_alloc);
867 842
868 843 cmd_list = &state->ts_cmd_list;
869 844 mutex_enter(&cmd_list->cml_lock);
870 845
871 846 /* Ensure that outstanding commands are supported */
872 847 ASSERT(cmd_list->cml_num_alloc != 0);
873 848
874 849 /*
875 850 * If the outstanding command list is empty, then wait (if
876 851 * appropriate in the current context). Otherwise, grab the
877 852 * next available command.
878 853 */
879 854 while (cmd_list->cml_entries_free == 0) {
↓ open down ↓ |
274 lines elided |
↑ open up ↑ |
880 855 /* No free commands */
881 856 if (cmd_wait == TAVOR_NOSLEEP) {
882 857 mutex_exit(&cmd_list->cml_lock);
883 858 TNF_PROBE_0(tavor_outstanding_cmd_alloc_fail,
884 859 TAVOR_TNF_ERROR, "");
885 860 TAVOR_TNF_EXIT(tavor_outstanding_cmd_alloc);
886 861 return (TAVOR_CMD_INSUFF_RSRC);
887 862 }
888 863
889 864 /*
890 - * Wait (on cv) for a command to become free. Note: Just
891 - * as we do above in tavor_cmd_post(), we also have the
892 - * "__lock_lint" here to workaround warlock. Warlock doesn't
893 - * know that other parts of the Tavor may occasionally call
894 - * this routine while holding their own locks, so it complains
895 - * about this cv_wait. In reality, however, the rest of the
896 - * driver never calls this routine with a lock held unless
897 - * they pass TAVOR_CMD_NOSLEEP.
865 + * Wait (on cv) for a command to become free.
898 866 */
899 867 cmd_list->cml_waiters++;
900 -#ifndef __lock_lint
901 868 cv_wait(&cmd_list->cml_cv, &cmd_list->cml_lock);
902 -#endif
903 869 }
904 870
905 871 /* Grab the next available command from the list */
906 872 head = cmd_list->cml_head_indx;
907 873 *cmd_ptr = &cmd_list->cml_cmd[head];
908 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(**cmd_ptr))
909 874 next = (*cmd_ptr)->cmd_next;
910 875 prev = (*cmd_ptr)->cmd_prev;
911 876 (*cmd_ptr)->cmd_status = TAVOR_CMD_INVALID_STATUS;
912 877
913 878 /* Remove it from the command list */
914 879 cmd_list->cml_cmd[next].cmd_prev = prev;
915 880 cmd_list->cml_cmd[prev].cmd_next = next;
916 881 cmd_list->cml_head_indx = next;
917 882
918 883 /* Update the "free" count and return */
919 884 cmd_list->cml_entries_free--;
920 885
921 886 mutex_exit(&cmd_list->cml_lock);
922 887
923 888 TAVOR_TNF_EXIT(tavor_outstanding_cmd_alloc);
924 889 return (TAVOR_CMD_SUCCESS);
925 890 }
926 891
927 892
928 893 /*
929 894 * tavor_outstanding_cmd_free()
930 895 * Context: Can be called only from base context.
931 896 */
932 897 static void
933 898 tavor_outstanding_cmd_free(tavor_state_t *state, tavor_cmd_t **cmd_ptr)
934 899 {
935 900 tavor_cmdlist_t *cmd_list;
936 901 uint_t cmd_indx;
937 902
938 903 TAVOR_TNF_ENTER(tavor_outstanding_cmd_free);
939 904
940 905 cmd_list = &state->ts_cmd_list;
941 906 mutex_enter(&cmd_list->cml_lock);
942 907
943 908 /* Pull the "index" from command entry */
944 909 cmd_indx = (*cmd_ptr)->cmd_indx;
945 910
946 911 /*
947 912 * If outstanding command list is not empty, then insert the entry.
948 913 * Otherwise, this is the only entry. So update the pointers
949 914 * appropriately.
950 915 */
951 916 if (cmd_list->cml_entries_free++ != 0) {
952 917 /* Update the current command */
953 918 (*cmd_ptr)->cmd_next = cmd_list->cml_head_indx;
954 919 (*cmd_ptr)->cmd_prev = cmd_list->cml_tail_indx;
955 920
956 921 /* Update head and tail commands */
957 922 cmd_list->cml_cmd[cmd_list->cml_head_indx].cmd_prev = cmd_indx;
958 923 cmd_list->cml_cmd[cmd_list->cml_tail_indx].cmd_next = cmd_indx;
959 924
960 925 /* Update tail index */
961 926 cmd_list->cml_tail_indx = cmd_indx;
962 927
963 928 } else {
964 929 /* Update the current command */
965 930 (*cmd_ptr)->cmd_next = cmd_indx;
966 931 (*cmd_ptr)->cmd_prev = cmd_indx;
967 932
968 933 /* Update head and tail indexes */
969 934 cmd_list->cml_head_indx = cmd_indx;
970 935 cmd_list->cml_tail_indx = cmd_indx;
971 936 }
972 937
973 938 /* If there are threads waiting, signal one of them */
974 939 if (cmd_list->cml_waiters > 0) {
975 940 cmd_list->cml_waiters--;
976 941 cv_signal(&cmd_list->cml_cv);
977 942 }
978 943
979 944 /* Clear out the command entry pointer */
980 945 *cmd_ptr = NULL;
981 946
982 947 mutex_exit(&cmd_list->cml_lock);
983 948
984 949 TAVOR_TNF_EXIT(tavor_outstanding_cmd_free);
985 950 }
986 951
987 952
988 953 /*
989 954 * tavor_write_hcr()
990 955 * Context: Can be called from interrupt or base context.
991 956 */
992 957 static int
993 958 tavor_write_hcr(tavor_state_t *state, tavor_cmd_post_t *cmdpost,
994 959 uint16_t token)
995 960 {
996 961 tavor_hw_hcr_t *hcr;
997 962 uint_t status, count, countmax;
↓ open down ↓ |
79 lines elided |
↑ open up ↑ |
998 963 uint64_t hcrreg;
999 964
1000 965 TAVOR_TNF_ENTER(tavor_write_hcr);
1001 966
1002 967 /*
1003 968 * Grab the "HCR access" lock if the driver is not in
1004 969 * fastreboot. In fastreboot, this function is called
1005 970 * with the single thread but in high interrupt context
1006 971 * (so that this mutex lock cannot be used).
1007 972 */
1008 -#ifdef __lock_lint
1009 - mutex_enter(&state->ts_cmd_regs.hcr_lock);
1010 -#else
1011 973 if (!TAVOR_IN_FASTREBOOT(state)) {
1012 974 mutex_enter(&state->ts_cmd_regs.hcr_lock);
1013 975 }
1014 -#endif
1015 976
1016 977 hcr = state->ts_cmd_regs.hcr;
1017 978
1018 979 /*
1019 980 * First, check the "go" bit to see if the previous hcr usage is
1020 981 * complete. As long as it is set then we must continue to poll.
1021 982 */
1022 983 count = 0;
1023 984 countmax = state->ts_cfg_profile->cp_cmd_poll_max;
1024 985 for (;;) {
1025 986 hcrreg = ddi_get32(state->ts_reg_cmdhdl, &hcr->cmd);
1026 987
1027 988 /* If "go" bit is clear, then done */
1028 989 if ((hcrreg & TAVOR_HCR_CMD_GO_MASK) == 0) {
1029 990 TNF_PROBE_1_DEBUG(tavor_write_hcr_loop_count,
1030 991 TAVOR_TNF_ERROR, "", tnf_uint, nospinloopcount,
1031 992 count);
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
1032 993 break;
1033 994 }
1034 995 /* Delay before polling the "go" bit again */
1035 996 drv_usecwait(state->ts_cfg_profile->cp_cmd_poll_delay);
1036 997
1037 998 /*
1038 999 * If we poll more than the maximum number of times, then
1039 1000 * return a "timeout" error.
1040 1001 */
1041 1002 if (++count > countmax) {
1042 -#ifdef __lock_lint
1043 - mutex_exit(&state->ts_cmd_regs.hcr_lock);
1044 -#else
1045 1003 if (!TAVOR_IN_FASTREBOOT(state)) {
1046 1004 mutex_exit(&state->ts_cmd_regs.hcr_lock);
1047 1005 }
1048 -#endif
1049 1006 TNF_PROBE_0(tavor_write_hcr_timeout1, TAVOR_TNF_ERROR,
1050 1007 "");
1051 1008 TAVOR_TNF_EXIT(tavor_write_hcr);
1052 1009 return (TAVOR_CMD_TIMEOUT);
1053 1010 }
1054 1011 }
1055 1012
1056 1013 /* Write "inparam" as a 64-bit quantity */
1057 1014 ddi_put64(state->ts_reg_cmdhdl, (uint64_t *)&hcr->in_param0,
1058 1015 cmdpost->cp_inparm);
1059 1016
1060 1017 /* Write "inmod" and 32-bits of "outparam" as 64-bit */
1061 1018 hcrreg = ((uint64_t)cmdpost->cp_inmod << 32);
1062 1019 hcrreg = hcrreg | (cmdpost->cp_outparm >> 32);
1063 1020 ddi_put64(state->ts_reg_cmdhdl, (uint64_t *)&hcr->input_modifier,
1064 1021 hcrreg);
1065 1022
1066 1023 /* Write the other 32-bits of "outparam" and "token" as 64-bit */
1067 1024 hcrreg = (cmdpost->cp_outparm << 32);
1068 1025 hcrreg = hcrreg | ((uint32_t)token << TAVOR_HCR_TOKEN_SHIFT);
1069 1026 ddi_put64(state->ts_reg_cmdhdl, (uint64_t *)&hcr->out_param1,
1070 1027 hcrreg);
1071 1028
1072 1029 /* Then setup the final hcrreg to hit doorbell (i.e. "go" bit) */
1073 1030 hcrreg = TAVOR_HCR_CMD_GO_MASK;
1074 1031 if (cmdpost->cp_flags == TAVOR_CMD_SLEEP_NOSPIN)
1075 1032 hcrreg = hcrreg | TAVOR_HCR_CMD_E_MASK;
1076 1033 hcrreg = hcrreg | (cmdpost->cp_opmod << TAVOR_HCR_CMD_OPMOD_SHFT);
1077 1034 hcrreg = hcrreg | (cmdpost->cp_opcode);
1078 1035
1079 1036 /* Write the doorbell to the HCR */
1080 1037 ddi_put32(state->ts_reg_cmdhdl, &hcr->cmd, hcrreg);
1081 1038
1082 1039 /*
1083 1040 * In the SPIN case we read the HCR and check the "go" bit. For the
1084 1041 * NOSPIN case we do not have to poll, we simply release the HCR lock
1085 1042 * and return.
1086 1043 */
1087 1044 if (cmdpost->cp_flags == TAVOR_CMD_NOSLEEP_SPIN) {
1088 1045 count = 0;
1089 1046 countmax = state->ts_cfg_profile->cp_cmd_poll_max;
1090 1047
1091 1048 for (;;) {
1092 1049 hcrreg = ddi_get32(state->ts_reg_cmdhdl, &hcr->cmd);
1093 1050
1094 1051 /* If "go" bit is clear, then done */
1095 1052 if ((hcrreg & TAVOR_HCR_CMD_GO_MASK) == 0) {
1096 1053 TNF_PROBE_1_DEBUG(tavor_write_hcr_loop_count,
1097 1054 TAVOR_TNF_ERROR, "", tnf_uint,
1098 1055 spinloopcount, count);
↓ open down ↓ |
40 lines elided |
↑ open up ↑ |
1099 1056 break;
1100 1057 }
1101 1058 /* Delay before polling the "go" bit again */
1102 1059 drv_usecwait(state->ts_cfg_profile->cp_cmd_poll_delay);
1103 1060
1104 1061 /*
1105 1062 * If we poll more than the maximum number of times,
1106 1063 * then return a "timeout" error.
1107 1064 */
1108 1065 if (++count > countmax) {
1109 -#ifdef __lock_lint
1110 - mutex_exit(&state-> ts_cmd_regs.hcr_lock);
1111 -#else
1112 1066 if (!TAVOR_IN_FASTREBOOT(state)) {
1113 1067 mutex_exit(&state->
1114 1068 ts_cmd_regs.hcr_lock);
1115 1069 }
1116 -#endif
1117 1070 TNF_PROBE_0(tavor_write_hcr_timeout2,
1118 1071 TAVOR_TNF_ERROR, "");
1119 1072 TAVOR_TNF_EXIT(tavor_write_hcr);
1120 1073 return (TAVOR_CMD_TIMEOUT);
1121 1074 }
1122 1075 }
1123 1076
1124 1077 /* Pull out the "status" bits from the HCR */
1125 1078 status = (hcrreg >> TAVOR_HCR_CMD_STATUS_SHFT);
1126 1079
1127 1080 /*
1128 1081 * Read the "outparam" value. Note: we have to read "outparam"
1129 1082 * as two separate 32-bit reads because the field in the HCR is
1130 1083 * not 64-bit aligned.
1131 1084 */
1132 1085 hcrreg = ddi_get32(state->ts_reg_cmdhdl, &hcr->out_param0);
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
1133 1086 cmdpost->cp_outparm = hcrreg << 32;
1134 1087 hcrreg = ddi_get32(state->ts_reg_cmdhdl, &hcr->out_param1);
1135 1088 cmdpost->cp_outparm |= hcrreg;
1136 1089
1137 1090 /* NOSPIN */
1138 1091 } else {
1139 1092 status = TAVOR_CMD_SUCCESS;
1140 1093 }
1141 1094
1142 1095 /* Drop the "HCR access" lock */
1143 -#ifdef __lock_lint
1144 - mutex_exit(&state->ts_cmd_regs.hcr_lock);
1145 -#else
1146 1096 if (!TAVOR_IN_FASTREBOOT(state)) {
1147 1097 mutex_exit(&state->ts_cmd_regs.hcr_lock);
1148 1098 }
1149 -#endif
1150 1099
1151 1100 TAVOR_TNF_EXIT(tavor_write_hcr);
1152 1101 return (status);
1153 1102 }
1154 1103
1155 1104
1156 1105 /*
1157 1106 * tavor_outstanding_cmdlist_init()
1158 1107 * Context: Only called from attach() path context
1159 1108 */
1160 1109 int
1161 1110 tavor_outstanding_cmdlist_init(tavor_state_t *state)
1162 1111 {
1163 1112 uint_t num_outstanding_cmds, head, tail;
1164 1113 int i;
1165 1114
1166 1115 TAVOR_TNF_ENTER(tavor_outstanding_cmdlist_init);
1167 1116
1168 1117 /*
1169 1118 * Determine the number of the outstanding commands supported
1170 1119 * by the Tavor device (obtained from the QUERY_FW command). Note:
1171 1120 * Because we handle both SLEEP and NOSLEEP cases around the tavor HCR,
1172 1121 * we know that when an interrupt comes in it will be next on the
1173 1122 * command register, and will at most have to wait one commands time.
1174 1123 * We do not have to reserve an outstanding command here for
1175 1124 * interrupts.
1176 1125 */
1177 1126 num_outstanding_cmds = (1 << state->ts_fw.log_max_cmd);
1178 1127
1179 1128 /* Initialize the outstanding command list */
1180 1129 state->ts_cmd_list.cml_list_sz = num_outstanding_cmds;
1181 1130 state->ts_cmd_list.cml_head_indx = 0;
1182 1131 state->ts_cmd_list.cml_tail_indx = state->ts_cmd_list.cml_list_sz - 1;
1183 1132 state->ts_cmd_list.cml_entries_free = state->ts_cmd_list.cml_list_sz;
1184 1133 state->ts_cmd_list.cml_waiters = 0;
1185 1134 state->ts_cmd_list.cml_num_alloc = 0;
1186 1135
1187 1136 /* Allocate the memory for the outstanding command list */
1188 1137 if (num_outstanding_cmds) {
1189 1138 state->ts_cmd_list.cml_cmd =
1190 1139 kmem_zalloc(state->ts_cmd_list.cml_list_sz *
1191 1140 sizeof (tavor_cmd_t), KM_SLEEP);
1192 1141 }
1193 1142 mutex_init(&state->ts_cmd_list.cml_lock, NULL, MUTEX_DRIVER,
1194 1143 DDI_INTR_PRI(state->ts_intrmsi_pri));
1195 1144 cv_init(&state->ts_cmd_list.cml_cv, NULL, CV_DRIVER, NULL);
1196 1145
1197 1146 /* Initialize the individual outstanding command list entries */
1198 1147 for (i = 0; i < state->ts_cmd_list.cml_list_sz; i++) {
1199 1148 mutex_init(&state->ts_cmd_list.cml_cmd[i].cmd_comp_lock,
1200 1149 NULL, MUTEX_DRIVER, DDI_INTR_PRI(state->ts_intrmsi_pri));
1201 1150 cv_init(&state->ts_cmd_list.cml_cmd[i].cmd_comp_cv, NULL,
1202 1151 CV_DRIVER, NULL);
1203 1152
1204 1153 state->ts_cmd_list.cml_cmd[i].cmd_next = i+1;
1205 1154 state->ts_cmd_list.cml_cmd[i].cmd_prev = i-1;
1206 1155 state->ts_cmd_list.cml_cmd[i].cmd_indx = i;
1207 1156 state->ts_cmd_list.cml_num_alloc = i + 1;
1208 1157 }
1209 1158 if (num_outstanding_cmds) {
1210 1159 head = state->ts_cmd_list.cml_head_indx;
1211 1160 tail = state->ts_cmd_list.cml_tail_indx;
1212 1161 state->ts_cmd_list.cml_cmd[head].cmd_prev =
1213 1162 state->ts_cmd_list.cml_tail_indx;
1214 1163 state->ts_cmd_list.cml_cmd[tail].cmd_next =
1215 1164 state->ts_cmd_list.cml_head_indx;
1216 1165 }
1217 1166
1218 1167 TAVOR_TNF_EXIT(tavor_outstanding_cmdlist_init);
1219 1168 return (DDI_SUCCESS);
1220 1169 }
1221 1170
1222 1171
1223 1172 /*
1224 1173 * tavor_outstanding_cmdlist_fini()
1225 1174 * Context: Only called from attach() and/or detach() path contexts
1226 1175 */
1227 1176 void
1228 1177 tavor_outstanding_cmdlist_fini(tavor_state_t *state)
1229 1178 {
1230 1179 int i;
1231 1180
1232 1181 TAVOR_TNF_ENTER(tavor_outstanding_cmdlist_fini);
1233 1182
1234 1183 /* Destroy the outstanding command list entries */
1235 1184 for (i = 0; i < state->ts_cmd_list.cml_num_alloc; i++) {
1236 1185 mutex_destroy(&state->ts_cmd_list.cml_cmd[i].cmd_comp_lock);
1237 1186 cv_destroy(&state->ts_cmd_list.cml_cmd[i].cmd_comp_cv);
1238 1187 }
1239 1188
1240 1189 /* Destroy the lock (and cv) and free up memory for list */
1241 1190 mutex_destroy(&state->ts_cmd_list.cml_lock);
1242 1191 cv_destroy(&state->ts_cmd_list.cml_cv);
1243 1192 if (state->ts_cmd_list.cml_num_alloc) {
1244 1193 kmem_free(state->ts_cmd_list.cml_cmd,
1245 1194 state->ts_cmd_list.cml_list_sz * sizeof (tavor_cmd_t));
1246 1195 }
1247 1196
1248 1197 TAVOR_TNF_EXIT(tavor_outstanding_cmdlist_fini);
1249 1198 }
1250 1199
1251 1200
1252 1201 /*
1253 1202 * tavor_mbox_sync()
1254 1203 */
1255 1204 static void
1256 1205 tavor_mbox_sync(tavor_mbox_t *mbox, uint_t offset, uint_t length,
1257 1206 uint_t flag)
1258 1207 {
1259 1208 ddi_dma_handle_t dmahdl;
1260 1209 int status;
1261 1210
1262 1211 TAVOR_TNF_ENTER(tavor_mbox_sync);
1263 1212
1264 1213 /* Determine if mailbox needs to be synced or not */
1265 1214 if (mbox->mb_sync == 0) {
1266 1215 TAVOR_TNF_EXIT(tavor_mbox_sync);
1267 1216 return;
1268 1217 }
1269 1218
1270 1219 /* Get the DMA handle from mailbox */
1271 1220 dmahdl = mbox->mb_rsrcptr->tr_dmahdl;
1272 1221
1273 1222 /* Calculate offset into mailbox */
1274 1223 status = ddi_dma_sync(dmahdl, (off_t)offset, (size_t)length, flag);
1275 1224 if (status != DDI_SUCCESS) {
1276 1225 TNF_PROBE_0(tavor_mbox_sync_fail, TAVOR_TNF_ERROR, "");
1277 1226 TAVOR_TNF_EXIT(tavor_mbox_sync);
1278 1227 return;
1279 1228 }
1280 1229
1281 1230 TAVOR_TNF_EXIT(tavor_mbox_sync);
1282 1231 }
1283 1232
1284 1233
1285 1234 /*
1286 1235 * tavor_sys_en_cmd_post()
1287 1236 * Context: Can be called from interrupt or base context.
1288 1237 * (Currently called only from attach() path context)
1289 1238 */
1290 1239 int
1291 1240 tavor_sys_en_cmd_post(tavor_state_t *state, uint_t flags,
1292 1241 uint64_t *errorcode, uint_t sleepflag)
1293 1242 {
1294 1243 tavor_cmd_post_t cmd;
1295 1244 int status;
1296 1245
1297 1246 TAVOR_TNF_ENTER(tavor_sys_en_cmd_post);
1298 1247
1299 1248 /* Make sure we are called with the correct flag */
1300 1249 ASSERT(sleepflag == TAVOR_CMD_NOSLEEP_SPIN);
1301 1250
1302 1251 /* Setup and post the Tavor "SYS_EN" command */
1303 1252 cmd.cp_inparm = 0;
1304 1253 cmd.cp_outparm = 0;
1305 1254 cmd.cp_inmod = 0;
1306 1255 cmd.cp_opcode = SYS_EN;
1307 1256 cmd.cp_opmod = flags;
1308 1257 cmd.cp_flags = sleepflag;
1309 1258 status = tavor_cmd_post(state, &cmd);
1310 1259 if (status != TAVOR_CMD_SUCCESS) {
1311 1260 TNF_PROBE_0(tavor_sys_en_cmd_post_fail, TAVOR_TNF_ERROR, "");
1312 1261 /*
1313 1262 * When the SYS_EN command fails, the "outparam" field may
1314 1263 * contain more detailed information about what caused the
1315 1264 * failure.
1316 1265 */
1317 1266 *errorcode = cmd.cp_outparm;
1318 1267 }
1319 1268
1320 1269 TAVOR_TNF_EXIT(tavor_sys_en_cmd_post);
1321 1270 return (status);
1322 1271 }
1323 1272
1324 1273
1325 1274 /*
1326 1275 * tavor_sys_dis_cmd_post()
1327 1276 * Context: Can be called from interrupt or base context.
1328 1277 * (Currently called only from attach() and/or detach() path contexts)
1329 1278 */
1330 1279 int
1331 1280 tavor_sys_dis_cmd_post(tavor_state_t *state, uint_t sleepflag)
1332 1281 {
1333 1282 tavor_cmd_post_t cmd;
1334 1283 int status;
1335 1284
1336 1285 TAVOR_TNF_ENTER(tavor_sys_dis_cmd_post);
1337 1286
1338 1287 /* Make sure we are called with the correct flag */
1339 1288 ASSERT(sleepflag == TAVOR_CMD_NOSLEEP_SPIN);
1340 1289
1341 1290 /* Setup and post the Tavor "SYS_DIS" command */
1342 1291 cmd.cp_inparm = 0;
1343 1292 cmd.cp_outparm = 0;
1344 1293 cmd.cp_inmod = 0;
1345 1294 cmd.cp_opcode = SYS_DIS;
1346 1295 cmd.cp_opmod = 0;
1347 1296 cmd.cp_flags = sleepflag;
1348 1297 status = tavor_cmd_post(state, &cmd);
1349 1298 if (status != TAVOR_CMD_SUCCESS) {
1350 1299 TNF_PROBE_0(tavor_sys_dis_cmd_post_fail,
1351 1300 TAVOR_TNF_ERROR, "");
1352 1301 }
1353 1302
1354 1303 TAVOR_TNF_EXIT(tavor_sys_dis_cmd_post);
1355 1304 return (status);
1356 1305 }
1357 1306
1358 1307
1359 1308 /*
1360 1309 * tavor_init_hca_cmd_post()
1361 1310 * Context: Can be called from interrupt or base context.
1362 1311 * (Currently called only from attach() path context)
1363 1312 */
1364 1313 int
1365 1314 tavor_init_hca_cmd_post(tavor_state_t *state,
1366 1315 tavor_hw_initqueryhca_t *inithca, uint_t sleepflag)
1367 1316 {
1368 1317 tavor_mbox_info_t mbox_info;
1369 1318 tavor_cmd_post_t cmd;
1370 1319 uint64_t data;
1371 1320 uint_t size;
1372 1321 int status, i;
1373 1322
1374 1323 TAVOR_TNF_ENTER(tavor_init_hca_cmd_post);
1375 1324
1376 1325 /* Make sure we are called with the correct flag */
1377 1326 ASSERT(sleepflag == TAVOR_CMD_NOSLEEP_SPIN);
1378 1327
1379 1328 /* Get an "In" mailbox for the command */
1380 1329 mbox_info.mbi_alloc_flags = TAVOR_ALLOC_INMBOX;
1381 1330 status = tavor_mbox_alloc(state, &mbox_info, sleepflag);
1382 1331 if (status != TAVOR_CMD_SUCCESS) {
1383 1332 TNF_PROBE_0(tavor_init_hca_mbox_fail, TAVOR_TNF_ERROR, "");
1384 1333 TAVOR_TNF_EXIT(tavor_init_hca_cmd_post);
1385 1334 return (status);
1386 1335 }
1387 1336
1388 1337 /* Copy the Tavor "INIT_HCA" command into the mailbox */
1389 1338 size = sizeof (tavor_hw_initqueryhca_t);
1390 1339 for (i = 0; i < (size >> 3); i++) {
1391 1340 data = ((uint64_t *)inithca)[i];
1392 1341 ddi_put64(mbox_info.mbi_in->mb_acchdl,
1393 1342 ((uint64_t *)mbox_info.mbi_in->mb_addr + i), data);
1394 1343 }
1395 1344
1396 1345 /* Sync the mailbox for the device to read */
1397 1346 tavor_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
1398 1347
1399 1348 /* Setup and post the Tavor "INIT_HCA" command */
1400 1349 cmd.cp_inparm = mbox_info.mbi_in->mb_mapaddr;
1401 1350 cmd.cp_outparm = 0;
1402 1351 cmd.cp_inmod = 0;
1403 1352 cmd.cp_opcode = INIT_HCA;
1404 1353 cmd.cp_opmod = 0;
1405 1354 cmd.cp_flags = sleepflag;
1406 1355 status = tavor_cmd_post(state, &cmd);
1407 1356 if (status != TAVOR_CMD_SUCCESS) {
1408 1357 TNF_PROBE_0(tavor_init_hca_cmd_post_fail,
1409 1358 TAVOR_TNF_ERROR, "");
1410 1359 }
1411 1360
1412 1361 /* Free the mailbox */
1413 1362 tavor_mbox_free(state, &mbox_info);
1414 1363
1415 1364 TAVOR_TNF_EXIT(tavor_init_hca_cmd_post);
1416 1365 return (status);
1417 1366 }
1418 1367
1419 1368
1420 1369 /*
1421 1370 * tavor_close_hca_cmd_post()
1422 1371 * Context: Can be called from interrupt or base context.
1423 1372 * (Currently called only from attach() and/or detach() path contexts)
1424 1373 */
1425 1374 int
1426 1375 tavor_close_hca_cmd_post(tavor_state_t *state, uint_t sleepflag)
1427 1376 {
1428 1377 tavor_cmd_post_t cmd;
1429 1378 int status;
1430 1379
1431 1380 TAVOR_TNF_ENTER(tavor_close_hca_cmd_post);
1432 1381
1433 1382 /* Make sure we are called with the correct flag */
1434 1383 ASSERT(sleepflag == TAVOR_CMD_NOSLEEP_SPIN);
1435 1384
1436 1385 /* Setup and post the Tavor "CLOSE_HCA" command */
1437 1386 cmd.cp_inparm = 0;
1438 1387 cmd.cp_outparm = 0;
1439 1388 cmd.cp_inmod = 0;
1440 1389 cmd.cp_opcode = CLOSE_HCA;
1441 1390 cmd.cp_opmod = 0;
1442 1391 cmd.cp_flags = sleepflag;
1443 1392 status = tavor_cmd_post(state, &cmd);
1444 1393 if (status != TAVOR_CMD_SUCCESS) {
1445 1394 TNF_PROBE_0(tavor_close_hca_cmd_post_fail,
1446 1395 TAVOR_TNF_ERROR, "");
1447 1396 }
1448 1397
1449 1398 TAVOR_TNF_EXIT(tavor_close_hca_cmd_post);
1450 1399 return (status);
1451 1400 }
1452 1401
1453 1402
1454 1403 /*
1455 1404 * tavor_init_ib_cmd_post()
1456 1405 * Context: Can be called from interrupt or base context.
1457 1406 * (Currently called only from attach() path context)
1458 1407 */
1459 1408 int
1460 1409 tavor_init_ib_cmd_post(tavor_state_t *state, tavor_hw_initib_t *initib,
1461 1410 uint_t port, uint_t sleepflag)
1462 1411 {
1463 1412 tavor_mbox_info_t mbox_info;
1464 1413 tavor_cmd_post_t cmd;
1465 1414 uint64_t data;
1466 1415 uint_t size;
1467 1416 int status, i;
1468 1417
1469 1418 TAVOR_TNF_ENTER(tavor_init_ib_cmd_post);
1470 1419
1471 1420 /* Make sure we are called with the correct flag */
1472 1421 ASSERT(sleepflag == TAVOR_CMD_NOSLEEP_SPIN);
1473 1422
1474 1423 /* Get an "In" mailbox for the command */
1475 1424 mbox_info.mbi_alloc_flags = TAVOR_ALLOC_INMBOX;
1476 1425 status = tavor_mbox_alloc(state, &mbox_info, sleepflag);
1477 1426 if (status != TAVOR_CMD_SUCCESS) {
1478 1427 TNF_PROBE_0(tavor_init_ib_mbox_fail, TAVOR_TNF_ERROR, "");
1479 1428 TAVOR_TNF_EXIT(tavor_init_ib_cmd_post);
1480 1429 return (status);
1481 1430 }
1482 1431
1483 1432 /* Copy the Tavor "INIT_IB" command into the mailbox */
1484 1433 size = sizeof (tavor_hw_initib_t);
1485 1434 for (i = 0; i < (size >> 3); i++) {
1486 1435 data = ((uint64_t *)initib)[i];
1487 1436 ddi_put64(mbox_info.mbi_in->mb_acchdl,
1488 1437 ((uint64_t *)mbox_info.mbi_in->mb_addr + i), data);
1489 1438 }
1490 1439
1491 1440 /* Sync the mailbox for the device to read */
1492 1441 tavor_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
1493 1442
1494 1443 /* Setup and post the Tavor "INIT_IB" command */
1495 1444 cmd.cp_inparm = mbox_info.mbi_in->mb_mapaddr;
1496 1445 cmd.cp_outparm = 0;
1497 1446 cmd.cp_inmod = port;
1498 1447 cmd.cp_opcode = INIT_IB;
1499 1448 cmd.cp_opmod = 0;
1500 1449 cmd.cp_flags = sleepflag;
1501 1450 status = tavor_cmd_post(state, &cmd);
1502 1451 if (status != TAVOR_CMD_SUCCESS) {
1503 1452 TNF_PROBE_0(tavor_init_ib_cmd_post_fail,
1504 1453 TAVOR_TNF_ERROR, "");
1505 1454 }
1506 1455
1507 1456 /* Free the mailbox */
1508 1457 tavor_mbox_free(state, &mbox_info);
1509 1458
1510 1459 TAVOR_TNF_EXIT(tavor_init_ib_cmd_post);
1511 1460 return (status);
1512 1461 }
1513 1462
1514 1463
1515 1464 /*
1516 1465 * tavor_close_ib_cmd_post()
1517 1466 * Context: Can be called from interrupt or base context.
1518 1467 * (Currently called only from attach() and/or detach() path contexts)
1519 1468 */
1520 1469 int
1521 1470 tavor_close_ib_cmd_post(tavor_state_t *state, uint_t port, uint_t sleepflag)
1522 1471 {
1523 1472 tavor_cmd_post_t cmd;
1524 1473 int status;
1525 1474
1526 1475 TAVOR_TNF_ENTER(tavor_close_ib_cmd_post);
1527 1476
1528 1477 /* Setup and post the Tavor "CLOSE_IB" command */
1529 1478 cmd.cp_inparm = 0;
1530 1479 cmd.cp_outparm = 0;
1531 1480 cmd.cp_inmod = port;
1532 1481 cmd.cp_opcode = CLOSE_IB;
1533 1482 cmd.cp_opmod = 0;
1534 1483 cmd.cp_flags = sleepflag;
1535 1484 status = tavor_cmd_post(state, &cmd);
1536 1485 if (status != TAVOR_CMD_SUCCESS) {
1537 1486 TNF_PROBE_0(tavor_close_ib_cmd_post_fail, TAVOR_TNF_ERROR, "");
1538 1487 }
1539 1488
1540 1489 TAVOR_TNF_EXIT(tavor_close_ib_cmd_post);
1541 1490 return (status);
1542 1491 }
1543 1492
1544 1493
1545 1494 /*
1546 1495 * tavor_set_ib_cmd_post()
1547 1496 * Context: Can be called from interrupt or base context.
1548 1497 */
1549 1498 int
1550 1499 tavor_set_ib_cmd_post(tavor_state_t *state, uint32_t capmask, uint_t port,
1551 1500 uint_t reset_qkey, uint_t sleepflag)
1552 1501 {
1553 1502 tavor_mbox_info_t mbox_info;
1554 1503 tavor_cmd_post_t cmd;
1555 1504 int status;
1556 1505
1557 1506 TAVOR_TNF_ENTER(tavor_set_ib_cmd_post);
1558 1507
1559 1508 /* Get an "In" mailbox for the command */
1560 1509 mbox_info.mbi_alloc_flags = TAVOR_ALLOC_INMBOX;
1561 1510 status = tavor_mbox_alloc(state, &mbox_info, sleepflag);
1562 1511 if (status != TAVOR_CMD_SUCCESS) {
1563 1512 TNF_PROBE_0(tavor_set_ib_mbox_fail, TAVOR_TNF_ERROR, "");
1564 1513 TAVOR_TNF_EXIT(tavor_set_ib_cmd_post);
1565 1514 return (status);
1566 1515 }
1567 1516
1568 1517 /* Copy the Tavor "SET_IB" command into mailbox */
1569 1518 ddi_put32(mbox_info.mbi_in->mb_acchdl,
1570 1519 ((uint32_t *)mbox_info.mbi_in->mb_addr + 0), reset_qkey);
1571 1520 ddi_put32(mbox_info.mbi_in->mb_acchdl,
1572 1521 ((uint32_t *)mbox_info.mbi_in->mb_addr + 1), capmask);
1573 1522
1574 1523 /* Sync the mailbox for the device to read */
1575 1524 tavor_mbox_sync(mbox_info.mbi_in, 0, TAVOR_CMD_SETIB_SZ,
1576 1525 DDI_DMA_SYNC_FORDEV);
1577 1526
1578 1527 /* Setup and post the Tavor "SET_IB" command */
1579 1528 cmd.cp_inparm = mbox_info.mbi_in->mb_mapaddr;
1580 1529 cmd.cp_outparm = 0;
1581 1530 cmd.cp_inmod = port;
1582 1531 cmd.cp_opcode = SET_IB;
1583 1532 cmd.cp_opmod = 0;
1584 1533 cmd.cp_flags = sleepflag;
1585 1534 status = tavor_cmd_post(state, &cmd);
1586 1535 if (status != TAVOR_CMD_SUCCESS) {
1587 1536 TNF_PROBE_0(tavor_set_ib_cmd_post_fail, TAVOR_TNF_ERROR, "");
1588 1537 }
1589 1538
1590 1539 /* Free the mailbox */
1591 1540 tavor_mbox_free(state, &mbox_info);
1592 1541
1593 1542 TAVOR_TNF_EXIT(tavor_set_ib_cmd_post);
1594 1543 return (status);
1595 1544 }
1596 1545
1597 1546
1598 1547 /*
1599 1548 * tavor_mod_stat_cfg_cmd_post()
1600 1549 * Context: Can be called only from attach() path
1601 1550 */
1602 1551 int
1603 1552 tavor_mod_stat_cfg_cmd_post(tavor_state_t *state)
1604 1553 {
1605 1554 tavor_mbox_info_t mbox_info;
1606 1555 tavor_cmd_post_t cmd;
1607 1556 tavor_hw_mod_stat_cfg_t *mod;
1608 1557 uint64_t data;
1609 1558 uint_t size;
1610 1559 int status, i;
1611 1560
1612 1561 TAVOR_TNF_ENTER(tavor_mod_stat_cfg_cmd_post);
1613 1562
1614 1563 /*
1615 1564 * "MOD_STAT_CFG" needs an INMBOX parameter, to specify what operations
1616 1565 * to do. However, at the point in time that we call this command, the
1617 1566 * DDR has not yet been initialized, and all INMBOX'es are located in
1618 1567 * DDR. Because we want to call MOD_STAT_CFG before QUERY_DEVLIM is
1619 1568 * called, and thus call it before DDR is setup, we simply use an
1620 1569 * OUTMBOX memory location here as our INMBOX parameter.
1621 1570 */
1622 1571 mbox_info.mbi_alloc_flags = TAVOR_ALLOC_OUTMBOX;
1623 1572 status = tavor_mbox_alloc(state, &mbox_info, TAVOR_NOSLEEP);
1624 1573 if (status != TAVOR_CMD_SUCCESS) {
1625 1574 TNF_PROBE_0(tavor_mod_stat_cfg_mbox_fail, TAVOR_TNF_ERROR, "");
1626 1575 TAVOR_TNF_EXIT(tavor_mod_stat_cfg_cmd_post);
1627 1576 return (status);
1628 1577 }
1629 1578
1630 1579 /*
1631 1580 * Allocate on the heap our 'mod_stat_cfg' structure. We want to
1632 1581 * ideally move all of this on to the stack in the future, but this
1633 1582 * works well for now.
1634 1583 */
1635 1584 mod = (tavor_hw_mod_stat_cfg_t *)kmem_zalloc(
1636 1585 sizeof (tavor_hw_mod_stat_cfg_t), KM_SLEEP);
1637 1586
1638 1587 /* Setup "MOD_STAT_CFG" settings */
1639 1588 mod->srq_m = 1;
1640 1589 mod->srq = state->ts_cfg_profile->cp_srq_enable;
1641 1590
1642 1591 if (mod->srq) {
1643 1592 mod->log_max_srq = state->ts_cfg_profile->cp_log_num_srq;
1644 1593 } else {
1645 1594 mod->log_max_srq = 0;
1646 1595 }
1647 1596
1648 1597 /* Copy the "MOD_STAT_CFG" command into the "In" mailbox */
1649 1598 size = sizeof (tavor_hw_mod_stat_cfg_t);
1650 1599 for (i = 0; i < (size >> 3); i++) {
1651 1600 data = ((uint64_t *)mod)[i];
1652 1601 ddi_put64(mbox_info.mbi_out->mb_acchdl,
1653 1602 ((uint64_t *)mbox_info.mbi_out->mb_addr + i), data);
1654 1603 }
1655 1604
1656 1605 /* Sync the mailbox for the device to read */
1657 1606 tavor_mbox_sync(mbox_info.mbi_out, 0, size, DDI_DMA_SYNC_FORDEV);
1658 1607
1659 1608 /* Setup and post the Tavor "MOD_STAT_CFG" command */
1660 1609 cmd.cp_inparm = mbox_info.mbi_out->mb_mapaddr;
1661 1610 cmd.cp_outparm = 0;
1662 1611 cmd.cp_inmod = 0;
1663 1612 cmd.cp_opcode = MOD_STAT_CFG;
1664 1613 cmd.cp_opmod = 0;
1665 1614 cmd.cp_flags = TAVOR_CMD_NOSLEEP_SPIN;
1666 1615 status = tavor_cmd_post(state, &cmd);
1667 1616 if (status != TAVOR_CMD_SUCCESS) {
1668 1617 TNF_PROBE_0(tavor_mod_stat_cfg_cmd_post_fail, TAVOR_TNF_ERROR,
1669 1618 "");
1670 1619 }
1671 1620
1672 1621 /* Free "MOD_STAT_CFG" struct */
1673 1622 kmem_free(mod, sizeof (tavor_hw_mod_stat_cfg_t));
1674 1623
1675 1624 /* Free the mailbox */
1676 1625 tavor_mbox_free(state, &mbox_info);
1677 1626
1678 1627 TAVOR_TNF_EXIT(tavor_mod_stat_cfg_cmd_post);
1679 1628 return (status);
1680 1629 }
1681 1630
1682 1631
1683 1632 /*
1684 1633 * tavor_mad_ifc_cmd_post()
1685 1634 * Context: Can be called from interrupt or base context.
1686 1635 */
1687 1636 int
1688 1637 tavor_mad_ifc_cmd_post(tavor_state_t *state, uint_t port,
1689 1638 uint_t sleepflag, uint32_t *mad, uint32_t *resp)
1690 1639 {
1691 1640 tavor_mbox_info_t mbox_info;
1692 1641 tavor_cmd_post_t cmd;
1693 1642 uint_t size;
1694 1643 int status;
1695 1644
1696 1645 TAVOR_TNF_ENTER(tavor_mad_ifc_cmd_post);
1697 1646
1698 1647 /* Get "In" and "Out" mailboxes for the command */
1699 1648 mbox_info.mbi_alloc_flags = TAVOR_ALLOC_INMBOX | TAVOR_ALLOC_OUTMBOX;
1700 1649 status = tavor_mbox_alloc(state, &mbox_info, sleepflag);
1701 1650 if (status != TAVOR_CMD_SUCCESS) {
1702 1651 TNF_PROBE_0(tavor_mad_ifc_mbox_fail, TAVOR_TNF_ERROR, "");
1703 1652 TAVOR_TNF_EXIT(tavor_mad_ifc_cmd_post);
1704 1653 return (status);
1705 1654 }
1706 1655
1707 1656 /* Copy the request MAD into the "In" mailbox */
1708 1657 size = TAVOR_CMD_MAD_IFC_SIZE;
1709 1658 bcopy(mad, mbox_info.mbi_in->mb_addr, size);
1710 1659
1711 1660 /* Sync the mailbox for the device to read */
1712 1661 tavor_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
1713 1662
1714 1663 /* Setup the Tavor "MAD_IFC" command */
1715 1664 cmd.cp_inparm = mbox_info.mbi_in->mb_mapaddr;
1716 1665 cmd.cp_outparm = mbox_info.mbi_out->mb_mapaddr;
1717 1666 cmd.cp_inmod = port;
1718 1667 cmd.cp_opcode = MAD_IFC;
1719 1668 cmd.cp_opmod = TAVOR_CMD_MKEY_CHECK; /* Enable MKey checking */
1720 1669 cmd.cp_flags = sleepflag;
1721 1670 status = tavor_cmd_post(state, &cmd);
1722 1671 if (status != TAVOR_CMD_SUCCESS) {
1723 1672 TNF_PROBE_0(tavor_mad_ifc_cmd_post_fail,
1724 1673 TAVOR_TNF_ERROR, "");
1725 1674 goto mad_ifc_fail;
1726 1675 }
1727 1676
1728 1677 /* Sync the mailbox to read the results */
1729 1678 tavor_mbox_sync(mbox_info.mbi_out, 0, size, DDI_DMA_SYNC_FORCPU);
1730 1679
1731 1680 /* Copy the response MAD into "resp" */
1732 1681 bcopy(mbox_info.mbi_out->mb_addr, resp, size);
1733 1682
1734 1683 mad_ifc_fail:
1735 1684 /* Free the mailbox */
1736 1685 tavor_mbox_free(state, &mbox_info);
1737 1686
1738 1687 TAVOR_TNF_EXIT(tavor_mad_ifc_cmd_post);
1739 1688 return (status);
1740 1689 }
1741 1690
1742 1691
1743 1692 /*
1744 1693 * tavor_getportinfo_cmd_post()
1745 1694 * Context: Can be called from interrupt or base context.
1746 1695 */
1747 1696 int
1748 1697 tavor_getportinfo_cmd_post(tavor_state_t *state, uint_t port,
1749 1698 uint_t sleepflag, sm_portinfo_t *portinfo)
1750 1699 {
1751 1700 tavor_mbox_info_t mbox_info;
1752 1701 tavor_cmd_post_t cmd;
1753 1702 uint32_t *mbox;
1754 1703 uint_t size;
1755 1704 int status, i;
1756 1705
1757 1706 TAVOR_TNF_ENTER(tavor_getportinfo_cmd_post);
1758 1707
1759 1708 /* Get "In" and "Out" mailboxes for the command */
1760 1709 mbox_info.mbi_alloc_flags = TAVOR_ALLOC_INMBOX | TAVOR_ALLOC_OUTMBOX;
1761 1710 status = tavor_mbox_alloc(state, &mbox_info, sleepflag);
1762 1711 if (status != TAVOR_CMD_SUCCESS) {
1763 1712 TNF_PROBE_0(tavor_getportinfo_mbox_fail,
1764 1713 TAVOR_TNF_ERROR, "");
1765 1714 TAVOR_TNF_EXIT(tavor_getportinfo_cmd_post);
1766 1715 return (status);
1767 1716 }
1768 1717
1769 1718 /* Build the GetPortInfo request MAD in the "In" mailbox */
1770 1719 size = TAVOR_CMD_MAD_IFC_SIZE;
1771 1720 mbox = (uint32_t *)mbox_info.mbi_in->mb_addr;
1772 1721 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[0], TAVOR_CMD_MADHDR0);
1773 1722 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[1], TAVOR_CMD_MADHDR1);
1774 1723 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[2], TAVOR_CMD_MADHDR2);
1775 1724 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[3], TAVOR_CMD_MADHDR3);
1776 1725 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[4], TAVOR_CMD_PORTINFO);
1777 1726 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[5], port);
1778 1727 for (i = 6; i < (size >> 2); i++) {
1779 1728 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[i], 0);
1780 1729 }
1781 1730
1782 1731 /* Sync the mailbox for the device to read */
1783 1732 tavor_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
1784 1733
1785 1734 /* Setup the Tavor "MAD_IFC" command */
1786 1735 cmd.cp_inparm = mbox_info.mbi_in->mb_mapaddr;
1787 1736 cmd.cp_outparm = mbox_info.mbi_out->mb_mapaddr;
1788 1737 cmd.cp_inmod = port;
1789 1738 cmd.cp_opcode = MAD_IFC;
1790 1739 cmd.cp_opmod = TAVOR_CMD_MKEY_DONTCHECK; /* No MKey checking */
1791 1740 cmd.cp_flags = sleepflag;
1792 1741 status = tavor_cmd_post(state, &cmd);
1793 1742 if (status != TAVOR_CMD_SUCCESS) {
1794 1743 TNF_PROBE_0(tavor_getportinfo_cmd_post_fail,
1795 1744 TAVOR_TNF_ERROR, "");
1796 1745 goto getportinfo_fail;
1797 1746 }
1798 1747
↓ open down ↓ |
639 lines elided |
↑ open up ↑ |
1799 1748 /* Sync the mailbox to read the results */
1800 1749 size = sizeof (sm_portinfo_t);
1801 1750 tavor_mbox_sync(mbox_info.mbi_out, TAVOR_CMD_MADDATA_OFFSET,
1802 1751 size, DDI_DMA_SYNC_FORCPU);
1803 1752
1804 1753 /*
1805 1754 * Copy GetPortInfo response MAD into "portinfo". Do any endian
1806 1755 * swapping that may be necessary to flip any of the "portinfo"
1807 1756 * fields
1808 1757 */
1809 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*portinfo))
1810 1758 bcopy((void *)((uintptr_t)mbox_info.mbi_out->mb_addr +
1811 1759 TAVOR_CMD_MADDATA_OFFSET), portinfo, size);
1812 1760 TAVOR_GETPORTINFO_SWAP(portinfo);
1813 - _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*portinfo))
1814 1761
1815 1762 getportinfo_fail:
1816 1763 /* Free the mailbox */
1817 1764 tavor_mbox_free(state, &mbox_info);
1818 1765
1819 1766 TAVOR_TNF_EXIT(tavor_getportinfo_cmd_post);
1820 1767 return (status);
1821 1768 }
1822 1769
1823 1770
1824 1771 /*
1825 1772 * tavor_getnodeinfo_cmd_post()
1826 1773 * Context: Can be called from interrupt or base context.
1827 1774 * (Currently called only from attach() and detach() path contexts)
1828 1775 */
1829 1776 int
1830 1777 tavor_getnodeinfo_cmd_post(tavor_state_t *state, uint_t sleepflag,
1831 1778 sm_nodeinfo_t *nodeinfo)
1832 1779 {
1833 1780 tavor_mbox_info_t mbox_info;
1834 1781 tavor_cmd_post_t cmd;
1835 1782 uint32_t *mbox;
1836 1783 uint_t size;
1837 1784 int status, i;
1838 1785
1839 1786 TAVOR_TNF_ENTER(tavor_getnodeinfo_cmd_post);
1840 1787
1841 1788 /* Make sure we are called with the correct flag */
1842 1789 ASSERT(sleepflag == TAVOR_CMD_NOSLEEP_SPIN);
1843 1790
1844 1791 /* Get "In" and "Out" mailboxes for the command */
1845 1792 mbox_info.mbi_alloc_flags = TAVOR_ALLOC_INMBOX | TAVOR_ALLOC_OUTMBOX;
1846 1793 status = tavor_mbox_alloc(state, &mbox_info, sleepflag);
1847 1794 if (status != TAVOR_CMD_SUCCESS) {
1848 1795 TNF_PROBE_0(tavor_getnodeinfo_mbox_fail,
1849 1796 TAVOR_TNF_ERROR, "");
1850 1797 TAVOR_TNF_EXIT(tavor_getnodeinfo_cmd_post);
1851 1798 return (status);
1852 1799 }
1853 1800
1854 1801 /* Build the GetNodeInfo request MAD into the "In" mailbox */
1855 1802 size = TAVOR_CMD_MAD_IFC_SIZE;
1856 1803 mbox = (uint32_t *)mbox_info.mbi_in->mb_addr;
1857 1804 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[0], TAVOR_CMD_MADHDR0);
1858 1805 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[1], TAVOR_CMD_MADHDR1);
1859 1806 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[2], TAVOR_CMD_MADHDR2);
1860 1807 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[3], TAVOR_CMD_MADHDR3);
1861 1808 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[4], TAVOR_CMD_NODEINFO);
1862 1809 for (i = 5; i < (size >> 2); i++) {
1863 1810 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[i], 0);
1864 1811 }
1865 1812
1866 1813 /* Sync the mailbox for the device to read */
1867 1814 tavor_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
1868 1815
1869 1816 /* Setup the Tavor "MAD_IFC" command */
1870 1817 cmd.cp_inparm = mbox_info.mbi_in->mb_mapaddr;
1871 1818 cmd.cp_outparm = mbox_info.mbi_out->mb_mapaddr;
1872 1819 cmd.cp_inmod = 1; /* Get NodeInfo from port #1 */
1873 1820 cmd.cp_opcode = MAD_IFC;
1874 1821 cmd.cp_opmod = TAVOR_CMD_MKEY_DONTCHECK; /* No MKey checking */
1875 1822 cmd.cp_flags = sleepflag;
1876 1823 status = tavor_cmd_post(state, &cmd);
1877 1824 if (status != TAVOR_CMD_SUCCESS) {
1878 1825 TNF_PROBE_0(tavor_getnodeinfo_cmd_post_fail,
1879 1826 TAVOR_TNF_ERROR, "");
1880 1827 goto getnodeinfo_fail;
1881 1828 }
1882 1829
1883 1830 /* Sync the mailbox to read the results */
1884 1831 size = sizeof (sm_nodeinfo_t);
1885 1832 tavor_mbox_sync(mbox_info.mbi_out, TAVOR_CMD_MADDATA_OFFSET,
1886 1833 size, DDI_DMA_SYNC_FORCPU);
1887 1834
1888 1835 /*
1889 1836 * Copy GetNodeInfo response MAD into "nodeinfo". Do any endian
1890 1837 * swapping that may be necessary to flip any of the "nodeinfo"
1891 1838 * fields
1892 1839 */
1893 1840 bcopy((void *)((uintptr_t)mbox_info.mbi_out->mb_addr +
1894 1841 TAVOR_CMD_MADDATA_OFFSET), nodeinfo, size);
1895 1842 TAVOR_GETNODEINFO_SWAP(nodeinfo);
1896 1843
1897 1844 getnodeinfo_fail:
1898 1845 /* Free the mailbox */
1899 1846 tavor_mbox_free(state, &mbox_info);
1900 1847
1901 1848 TAVOR_TNF_EXIT(tavor_getnodeinfo_cmd_post);
1902 1849 return (status);
1903 1850 }
1904 1851
1905 1852
1906 1853 /*
1907 1854 * tavor_getnodedesc_cmd_post()
1908 1855 * Context: Can be called from interrupt or base context.
1909 1856 * (Currently called only from attach() and detach() path contexts)
1910 1857 */
1911 1858 int
1912 1859 tavor_getnodedesc_cmd_post(tavor_state_t *state, uint_t sleepflag,
1913 1860 sm_nodedesc_t *nodedesc)
1914 1861 {
1915 1862 tavor_mbox_info_t mbox_info;
1916 1863 tavor_cmd_post_t cmd;
1917 1864 uint32_t *mbox;
1918 1865 uint_t size;
1919 1866 int status, i;
1920 1867
1921 1868 TAVOR_TNF_ENTER(tavor_getnodedesc_cmd_post);
1922 1869
1923 1870 /* Get "In" and "Out" mailboxes for the command */
1924 1871 mbox_info.mbi_alloc_flags = TAVOR_ALLOC_INMBOX | TAVOR_ALLOC_OUTMBOX;
1925 1872 status = tavor_mbox_alloc(state, &mbox_info, sleepflag);
1926 1873 if (status != TAVOR_CMD_SUCCESS) {
1927 1874 TNF_PROBE_0(tavor_getnodedesc_mbox_fail, TAVOR_TNF_ERROR, "");
1928 1875 TAVOR_TNF_EXIT(tavor_getnodedesc_cmd_post);
1929 1876 return (status);
1930 1877 }
1931 1878
1932 1879 /* Build the GetNodeDesc request MAD into the "In" mailbox */
1933 1880 size = TAVOR_CMD_MAD_IFC_SIZE;
1934 1881 mbox = (uint32_t *)mbox_info.mbi_in->mb_addr;
1935 1882 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[0], TAVOR_CMD_MADHDR0);
1936 1883 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[1], TAVOR_CMD_MADHDR1);
1937 1884 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[2], TAVOR_CMD_MADHDR2);
1938 1885 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[3], TAVOR_CMD_MADHDR3);
1939 1886 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[4], TAVOR_CMD_NODEDESC);
1940 1887 for (i = 5; i < (size >> 2); i++) {
1941 1888 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[i], 0);
1942 1889 }
1943 1890
1944 1891 /* Sync the mailbox for the device to read */
1945 1892 tavor_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
1946 1893
1947 1894 /* Setup the Tavor "MAD_IFC" command */
1948 1895 cmd.cp_inparm = mbox_info.mbi_in->mb_mapaddr;
1949 1896 cmd.cp_outparm = mbox_info.mbi_out->mb_mapaddr;
1950 1897 cmd.cp_inmod = 1; /* Get NodeDesc from port #1 */
1951 1898 cmd.cp_opcode = MAD_IFC;
1952 1899 cmd.cp_opmod = TAVOR_CMD_MKEY_DONTCHECK; /* No MKey checking */
1953 1900 cmd.cp_flags = sleepflag;
1954 1901 status = tavor_cmd_post(state, &cmd);
1955 1902 if (status != TAVOR_CMD_SUCCESS) {
1956 1903 TNF_PROBE_0(tavor_getnodedesc_cmd_post_fail,
1957 1904 TAVOR_TNF_ERROR, "");
1958 1905 goto getnodedesc_fail;
1959 1906 }
1960 1907
1961 1908 /* Sync the mailbox to read the results */
1962 1909 size = sizeof (sm_nodedesc_t);
1963 1910 tavor_mbox_sync(mbox_info.mbi_out, TAVOR_CMD_MADDATA_OFFSET,
1964 1911 size, DDI_DMA_SYNC_FORCPU);
1965 1912
1966 1913 /* Copy GetNodeDesc response MAD into "nodedesc" */
1967 1914 bcopy((void *)((uintptr_t)mbox_info.mbi_out->mb_addr +
1968 1915 TAVOR_CMD_MADDATA_OFFSET), nodedesc, size);
1969 1916
1970 1917 getnodedesc_fail:
1971 1918 /* Free the mailbox */
1972 1919 tavor_mbox_free(state, &mbox_info);
1973 1920
1974 1921 TAVOR_TNF_EXIT(tavor_getnodedesc_cmd_post);
1975 1922 return (status);
1976 1923 }
1977 1924
1978 1925
1979 1926 /*
1980 1927 * tavor_getguidinfo_cmd_post()
1981 1928 * Context: Can be called from interrupt or base context.
1982 1929 */
1983 1930 int
1984 1931 tavor_getguidinfo_cmd_post(tavor_state_t *state, uint_t port,
1985 1932 uint_t guidblock, uint_t sleepflag, sm_guidinfo_t *guidinfo)
1986 1933 {
1987 1934 tavor_mbox_info_t mbox_info;
1988 1935 tavor_cmd_post_t cmd;
1989 1936 uint32_t *mbox;
1990 1937 uint_t size;
1991 1938 int status, i;
1992 1939
1993 1940 TAVOR_TNF_ENTER(tavor_getguidinfo_cmd_post);
1994 1941
1995 1942 /* Get "In" and "Out" mailboxes for the command */
1996 1943 mbox_info.mbi_alloc_flags = TAVOR_ALLOC_INMBOX | TAVOR_ALLOC_OUTMBOX;
1997 1944 status = tavor_mbox_alloc(state, &mbox_info, sleepflag);
1998 1945 if (status != TAVOR_CMD_SUCCESS) {
1999 1946 TNF_PROBE_0(tavor_getguidinfo_mbox_fail, TAVOR_TNF_ERROR, "");
2000 1947 TAVOR_TNF_EXIT(tavor_getguidinfo_cmd_post);
2001 1948 return (status);
2002 1949 }
2003 1950
2004 1951 /* Build the GetGUIDInfo request MAD into the "In" mailbox */
2005 1952 size = TAVOR_CMD_MAD_IFC_SIZE;
2006 1953 mbox = (uint32_t *)mbox_info.mbi_in->mb_addr;
2007 1954 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[0], TAVOR_CMD_MADHDR0);
2008 1955 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[1], TAVOR_CMD_MADHDR1);
2009 1956 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[2], TAVOR_CMD_MADHDR2);
2010 1957 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[3], TAVOR_CMD_MADHDR3);
2011 1958 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[4], TAVOR_CMD_GUIDINFO);
2012 1959 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[5], guidblock);
2013 1960 for (i = 6; i < (size >> 2); i++) {
2014 1961 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[i], 0);
2015 1962 }
2016 1963
2017 1964 /* Sync the mailbox for the device to read */
2018 1965 tavor_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
2019 1966
2020 1967 /* Setup the Tavor "MAD_IFC" command */
2021 1968 cmd.cp_inparm = mbox_info.mbi_in->mb_mapaddr;
2022 1969 cmd.cp_outparm = mbox_info.mbi_out->mb_mapaddr;
2023 1970 cmd.cp_inmod = port;
2024 1971 cmd.cp_opcode = MAD_IFC;
2025 1972 cmd.cp_opmod = TAVOR_CMD_MKEY_DONTCHECK; /* No MKey checking */
2026 1973 cmd.cp_flags = sleepflag;
2027 1974 status = tavor_cmd_post(state, &cmd);
2028 1975 if (status != TAVOR_CMD_SUCCESS) {
2029 1976 TNF_PROBE_0(tavor_getguidinfo_cmd_post_fail,
2030 1977 TAVOR_TNF_ERROR, "");
2031 1978 goto getguidinfo_fail;
2032 1979 }
↓ open down ↓ |
209 lines elided |
↑ open up ↑ |
2033 1980
2034 1981 /* Sync the mailbox to read the results */
2035 1982 size = sizeof (sm_guidinfo_t);
2036 1983 tavor_mbox_sync(mbox_info.mbi_out, TAVOR_CMD_MADDATA_OFFSET,
2037 1984 size, DDI_DMA_SYNC_FORCPU);
2038 1985
2039 1986 /*
2040 1987 * Copy GetGUIDInfo response MAD into "guidinfo". Do any endian
2041 1988 * swapping that may be necessary to flip the "guidinfo" fields
2042 1989 */
2043 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*guidinfo))
2044 1990 bcopy((void *)((uintptr_t)mbox_info.mbi_out->mb_addr +
2045 1991 TAVOR_CMD_MADDATA_OFFSET), guidinfo, size);
2046 1992 TAVOR_GETGUIDINFO_SWAP(guidinfo);
2047 - _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*guidinfo))
2048 1993
2049 1994 getguidinfo_fail:
2050 1995 /* Free the mailbox */
2051 1996 tavor_mbox_free(state, &mbox_info);
2052 1997
2053 1998 TAVOR_TNF_EXIT(tavor_getguidinfo_cmd_post);
2054 1999 return (status);
2055 2000 }
2056 2001
2057 2002
2058 2003 /*
2059 2004 * tavor_getpkeytable_cmd_post()
2060 2005 * Context: Can be called from interrupt or base context.
2061 2006 */
2062 2007 int
2063 2008 tavor_getpkeytable_cmd_post(tavor_state_t *state, uint_t port,
2064 2009 uint_t pkeyblock, uint_t sleepflag, sm_pkey_table_t *pkeytable)
2065 2010 {
2066 2011 tavor_mbox_info_t mbox_info;
2067 2012 tavor_cmd_post_t cmd;
2068 2013 uint32_t *mbox;
2069 2014 uint_t size;
2070 2015 int status, i;
2071 2016
2072 2017 TAVOR_TNF_ENTER(tavor_getpkeytable_cmd_post);
2073 2018
2074 2019 /* Get "In" and "Out" mailboxes for the command */
2075 2020 mbox_info.mbi_alloc_flags = TAVOR_ALLOC_INMBOX | TAVOR_ALLOC_OUTMBOX;
2076 2021 status = tavor_mbox_alloc(state, &mbox_info, sleepflag);
2077 2022 if (status != TAVOR_CMD_SUCCESS) {
2078 2023 TNF_PROBE_0(tavor_getpkeytable_mbox_fail, TAVOR_TNF_ERROR, "");
2079 2024 TAVOR_TNF_EXIT(tavor_getpkeytable_cmd_post);
2080 2025 return (status);
2081 2026 }
2082 2027
2083 2028 /* Build the GetPkeyTable request MAD into the "In" mailbox */
2084 2029 size = TAVOR_CMD_MAD_IFC_SIZE;
2085 2030 mbox = (uint32_t *)mbox_info.mbi_in->mb_addr;
2086 2031 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[0], TAVOR_CMD_MADHDR0);
2087 2032 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[1], TAVOR_CMD_MADHDR1);
2088 2033 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[2], TAVOR_CMD_MADHDR2);
2089 2034 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[3], TAVOR_CMD_MADHDR3);
2090 2035 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[4], TAVOR_CMD_PKEYTBLE);
2091 2036 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[5], pkeyblock);
2092 2037 for (i = 6; i < (size >> 2); i++) {
2093 2038 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[i], 0);
2094 2039 }
2095 2040
2096 2041 /* Sync the mailbox for the device to read */
2097 2042 tavor_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
2098 2043
2099 2044 /* Setup the Tavor "MAD_IFC" command */
2100 2045 cmd.cp_inparm = mbox_info.mbi_in->mb_mapaddr;
2101 2046 cmd.cp_outparm = mbox_info.mbi_out->mb_mapaddr;
2102 2047 cmd.cp_inmod = port;
2103 2048 cmd.cp_opcode = MAD_IFC;
2104 2049 cmd.cp_opmod = TAVOR_CMD_MKEY_DONTCHECK; /* No MKey checking */
2105 2050 cmd.cp_flags = sleepflag;
2106 2051 status = tavor_cmd_post(state, &cmd);
2107 2052 if (status != TAVOR_CMD_SUCCESS) {
2108 2053 TNF_PROBE_0(tavor_getpkeytable_cmd_post_fail,
2109 2054 TAVOR_TNF_ERROR, "");
2110 2055 goto getpkeytable_fail;
2111 2056 }
↓ open down ↓ |
54 lines elided |
↑ open up ↑ |
2112 2057
2113 2058 /* Sync the mailbox to read the results */
2114 2059 size = sizeof (sm_pkey_table_t);
2115 2060 tavor_mbox_sync(mbox_info.mbi_out, TAVOR_CMD_MADDATA_OFFSET,
2116 2061 size, DDI_DMA_SYNC_FORCPU);
2117 2062
2118 2063 /*
2119 2064 * Copy GetPKeyTable response MAD into "pkeytable". Do any endian
2120 2065 * swapping that may be necessary to flip the "pkeytable" fields
2121 2066 */
2122 - _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*pkeytable))
2123 2067 bcopy((void *)((uintptr_t)mbox_info.mbi_out->mb_addr +
2124 2068 TAVOR_CMD_MADDATA_OFFSET), pkeytable, size);
2125 2069 TAVOR_GETPKEYTABLE_SWAP(pkeytable);
2126 - _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*pkeytable))
2127 2070
2128 2071 getpkeytable_fail:
2129 2072 /* Free the mailbox */
2130 2073 tavor_mbox_free(state, &mbox_info);
2131 2074
2132 2075 TAVOR_TNF_EXIT(tavor_getpkeytable_cmd_post);
2133 2076 return (status);
2134 2077 }
2135 2078
2136 2079
2137 2080 /*
2138 2081 * tavor_write_mtt_cmd_post()
2139 2082 * Context: Can be called from interrupt or base context.
2140 2083 */
2141 2084 int
2142 2085 tavor_write_mtt_cmd_post(tavor_state_t *state, tavor_mbox_info_t *mbox_info,
2143 2086 uint_t num_mtt, uint_t sleepflag)
2144 2087 {
2145 2088 tavor_cmd_post_t cmd;
2146 2089 uint_t size;
2147 2090 int status;
2148 2091
2149 2092 TAVOR_TNF_ENTER(tavor_write_mtt_cmd_post);
2150 2093
2151 2094 /*
2152 2095 * The WRITE_MTT command is unlike the other commands we use, in that
2153 2096 * we have intentionally separated the mailbox allocation step from
2154 2097 * the rest of the command posting steps. At this point (when this
2155 2098 * function is called) the "In" mailbox already contains all the MTT
2156 2099 * entries to be copied into the Tavor tables (starting at offset
2157 2100 * 0x10) _and_ the 64-bit address of the destination for the first
2158 2101 * MTT entry in the MTT table.
2159 2102 */
2160 2103
2161 2104 /* Sync the mailbox for the device to read */
2162 2105 size = (num_mtt << TAVOR_MTT_SIZE_SHIFT) + TAVOR_CMD_WRITEMTT_RSVD_SZ;
2163 2106 tavor_mbox_sync(mbox_info->mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
2164 2107
2165 2108 /* Setup and post Tavor "WRITE_MTT" command */
2166 2109 cmd.cp_inparm = mbox_info->mbi_in->mb_mapaddr;
2167 2110 cmd.cp_outparm = 0;
2168 2111 cmd.cp_inmod = num_mtt;
2169 2112 cmd.cp_opcode = WRITE_MTT;
2170 2113 cmd.cp_opmod = 0;
2171 2114 cmd.cp_flags = sleepflag;
2172 2115 status = tavor_cmd_post(state, &cmd);
2173 2116 if (status != TAVOR_CMD_SUCCESS) {
2174 2117 TNF_PROBE_0(tavor_write_mtt_cmd_fail, TAVOR_TNF_ERROR, "");
2175 2118 }
2176 2119
2177 2120 TAVOR_TNF_EXIT(tavor_write_mtt_cmd_post);
2178 2121 return (status);
2179 2122 }
2180 2123
2181 2124
2182 2125 /*
2183 2126 * tavor_sync_tpt_cmd_post()
2184 2127 * Context: Can be called from interrupt or base context.
2185 2128 */
2186 2129 int
2187 2130 tavor_sync_tpt_cmd_post(tavor_state_t *state, uint_t sleepflag)
2188 2131 {
2189 2132 tavor_cmd_post_t cmd;
2190 2133 int status;
2191 2134
2192 2135 TAVOR_TNF_ENTER(tavor_sync_tpt_cmd_post);
2193 2136
2194 2137 /* Setup and post the Tavor "SYNC_TPT" command */
2195 2138 cmd.cp_inparm = 0;
2196 2139 cmd.cp_outparm = 0;
2197 2140 cmd.cp_inmod = 0;
2198 2141 cmd.cp_opcode = SYNC_TPT;
2199 2142 cmd.cp_opmod = 0;
2200 2143 cmd.cp_flags = sleepflag;
2201 2144 status = tavor_cmd_post(state, &cmd);
2202 2145 if (status != TAVOR_CMD_SUCCESS) {
2203 2146 TNF_PROBE_0(tavor_sync_tpt_cmd_post_fail, TAVOR_TNF_ERROR, "");
2204 2147 }
2205 2148
2206 2149 TAVOR_TNF_EXIT(tavor_sync_tpt_cmd_post);
2207 2150 return (status);
2208 2151 }
2209 2152
2210 2153 /*
2211 2154 * tavor_map_eq_cmd_post()
2212 2155 * Context: Can be called from interrupt or base context.
2213 2156 * (Currently called only from attach() and/or detach() path contexts)
2214 2157 */
2215 2158 int
2216 2159 tavor_map_eq_cmd_post(tavor_state_t *state, uint_t map, uint_t eqcindx,
2217 2160 uint64_t eqmapmask, uint_t sleepflag)
2218 2161 {
2219 2162 tavor_cmd_post_t cmd;
2220 2163 int status;
2221 2164
2222 2165 TAVOR_TNF_ENTER(tavor_map_eq_cmd_post);
2223 2166
2224 2167 /* Setup and post Tavor "MAP_EQ" command */
2225 2168 cmd.cp_inparm = eqmapmask;
2226 2169 cmd.cp_outparm = 0;
2227 2170 cmd.cp_inmod = eqcindx;
2228 2171 if (map != TAVOR_CMD_MAP_EQ_EVT_MAP) {
2229 2172 cmd.cp_inmod |= TAVOR_CMD_UNMAP_EQ_MASK;
2230 2173 }
2231 2174 cmd.cp_opcode = MAP_EQ;
2232 2175 cmd.cp_opmod = 0;
2233 2176 cmd.cp_flags = sleepflag;
2234 2177 status = tavor_cmd_post(state, &cmd);
2235 2178 if (status != TAVOR_CMD_SUCCESS) {
2236 2179 TNF_PROBE_0(tavor_map_eq_cmd_post_fail, TAVOR_TNF_ERROR, "");
2237 2180 }
2238 2181
2239 2182 TAVOR_TNF_EXIT(tavor_map_eq_cmd_post);
2240 2183 return (status);
2241 2184 }
2242 2185
2243 2186
2244 2187 /*
2245 2188 * tavor_resize_cq_cmd_post()
2246 2189 * Context: Can be called from interrupt or base context.
2247 2190 */
2248 2191 int
2249 2192 tavor_resize_cq_cmd_post(tavor_state_t *state, tavor_hw_cqc_t *cqc,
2250 2193 uint_t cqcindx, uint32_t *prod_indx, uint_t sleepflag)
2251 2194 {
2252 2195 tavor_mbox_info_t mbox_info;
2253 2196 tavor_cmd_post_t cmd;
2254 2197 uint64_t data;
2255 2198 uint_t size;
2256 2199 int status, i;
2257 2200
2258 2201 TAVOR_TNF_ENTER(tavor_resize_cq_cmd_post);
2259 2202
2260 2203 /* Get an "In" mailbox for the command */
2261 2204 mbox_info.mbi_alloc_flags = TAVOR_ALLOC_INMBOX;
2262 2205 status = tavor_mbox_alloc(state, &mbox_info, sleepflag);
2263 2206 if (status != TAVOR_CMD_SUCCESS) {
2264 2207 TNF_PROBE_0(tavor_resize_cq_mbox_fail, TAVOR_TNF_ERROR, "");
2265 2208 TAVOR_TNF_EXIT(tavor_resize_cq_cmd_post);
2266 2209 return (status);
2267 2210 }
2268 2211
2269 2212 /* Copy the Tavor "RESIZE_CQ" command into mailbox */
2270 2213 size = sizeof (tavor_hw_cqc_t);
2271 2214 for (i = 0; i < (size >> 3); i++) {
2272 2215 data = ((uint64_t *)cqc)[i];
2273 2216 ddi_put64(mbox_info.mbi_in->mb_acchdl,
2274 2217 ((uint64_t *)mbox_info.mbi_in->mb_addr + i), data);
2275 2218 }
2276 2219
2277 2220 /* Sync the mailbox for the device to read */
2278 2221 tavor_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
2279 2222
2280 2223 /* Setup and post Tavor "RESIZE_CQ" command */
2281 2224 cmd.cp_inparm = mbox_info.mbi_in->mb_mapaddr;
2282 2225 cmd.cp_outparm = 0;
2283 2226 cmd.cp_inmod = cqcindx;
2284 2227 cmd.cp_opcode = RESIZE_CQ;
2285 2228 cmd.cp_opmod = 0;
2286 2229 cmd.cp_flags = sleepflag;
2287 2230 status = tavor_cmd_post(state, &cmd);
2288 2231 if (status != TAVOR_CMD_SUCCESS) {
2289 2232 TNF_PROBE_0(tavor_resize_cq_cmd_post_fail, TAVOR_TNF_ERROR, "");
2290 2233 }
2291 2234
2292 2235 /*
2293 2236 * New "producer index" is returned in the upper 32 bits of
2294 2237 * command "outparam"
2295 2238 */
2296 2239 *prod_indx = (cmd.cp_outparm >> 32);
2297 2240
2298 2241 /* Free the mailbox */
2299 2242 tavor_mbox_free(state, &mbox_info);
2300 2243
2301 2244 TAVOR_TNF_EXIT(tavor_resize_cq_cmd_post);
2302 2245 return (status);
2303 2246 }
2304 2247
2305 2248
2306 2249 /*
2307 2250 * tavor_cmn_qp_cmd_post()
2308 2251 * Context: Can be called from interrupt or base context.
2309 2252 *
2310 2253 * This is the common function for posting all the various types of
2311 2254 * QP state transition related Tavor commands. Since some of the
2312 2255 * commands differ from the others in the number (and type) of arguments
2313 2256 * that each require, this routine does checks based on opcode type
2314 2257 * (explained in more detail below).
2315 2258 *
2316 2259 * Note: This common function should be used only with the following
2317 2260 * opcodes: RTS2SQD_QP, TOERR_QP, TORST_QP, RST2INIT_QP, INIT2INIT_QP,
2318 2261 * INIT2RTR_QP, RTR2RTS_QP, RTS2RTS_QP, SQD2RTS_QP, and SQERR2RTS_QP.
2319 2262 */
2320 2263 int
2321 2264 tavor_cmn_qp_cmd_post(tavor_state_t *state, uint_t opcode,
2322 2265 tavor_hw_qpc_t *qp, uint_t qpindx, uint32_t opmask,
2323 2266 uint_t sleepflag)
2324 2267 {
2325 2268 tavor_mbox_info_t mbox_info;
2326 2269 tavor_cmd_post_t cmd;
2327 2270 uint64_t data, in_mapaddr, out_mapaddr;
2328 2271 uint_t size, flags, opmod;
2329 2272 int status, i;
2330 2273
2331 2274 TAVOR_TNF_ENTER(tavor_cmn_qp_cmd_post);
2332 2275
2333 2276 /*
2334 2277 * Use the specified opcode type to set the appropriate parameters.
2335 2278 * Specifically, we need to set in_mapaddr, out_mapaddr, flags, and
2336 2279 * opmod (as necessary). Setting these parameters may also require
2337 2280 * us to allocate an "In" or "Out" mailbox depending on the command
2338 2281 * type.
2339 2282 */
2340 2283 if (opcode == RTS2SQD_QP) {
2341 2284 /*
2342 2285 * Note: For RTS-to-SendQueueDrain state transitions we
2343 2286 * always want to request the event generation from the
2344 2287 * hardware. Though we may not notify the consumer of the
2345 2288 * drained event, the decision to forward (or not) is made
2346 2289 * later in the SQD event handler.
2347 2290 */
2348 2291 flags = TAVOR_CMD_REQ_SQD_EVENT;
2349 2292
2350 2293 /*
2351 2294 * The RTS2SQD_QP command uses no "In" or "Out" mailboxes (and
2352 2295 * has no special opcode modifiers).
2353 2296 */
2354 2297 in_mapaddr = 0;
2355 2298 out_mapaddr = 0;
2356 2299 opmod = 0;
2357 2300
2358 2301 } else if (opcode == TOERR_QP) {
2359 2302 /*
2360 2303 * The TOERR_QP command uses no "In" or "Out" mailboxes, has no
2361 2304 * special opcode modifiers, and takes no special flags.
2362 2305 */
2363 2306 in_mapaddr = 0;
2364 2307 out_mapaddr = 0;
2365 2308 opmod = 0;
2366 2309 flags = 0;
2367 2310
2368 2311 } else if (opcode == TORST_QP) {
2369 2312 /*
2370 2313 * The TORST_QP command could take an "Out" mailbox, but we do
2371 2314 * not require it here. It also does not takes any special
2372 2315 * flags. It does however, take a TAVOR_CMD_DIRECT_TO_RESET
2373 2316 * opcode modifier, which indicates that the transition to
2374 2317 * reset should happen without first moving the QP through the
2375 2318 * Error state (and, hence, without generating any unnecessary
2376 2319 * "flushed-in-error" completions).
2377 2320 */
2378 2321 in_mapaddr = 0;
2379 2322 out_mapaddr = 0;
2380 2323 opmod = TAVOR_CMD_DIRECT_TO_RESET | TAVOR_CMD_NO_OUTMBOX;
2381 2324 flags = 0;
2382 2325
2383 2326 } else {
2384 2327 /*
2385 2328 * All the other QP state transition commands (RST2INIT_QP,
2386 2329 * INIT2INIT_QP, INIT2RTR_QP, RTR2RTS_QP, RTS2RTS_QP,
2387 2330 * SQD2RTS_QP, and SQERR2RTS_QP) require an "In" mailbox.
2388 2331 * None of these require any special flags or opcode modifiers.
2389 2332 */
2390 2333 mbox_info.mbi_alloc_flags = TAVOR_ALLOC_INMBOX;
2391 2334 status = tavor_mbox_alloc(state, &mbox_info, sleepflag);
2392 2335 if (status != TAVOR_CMD_SUCCESS) {
2393 2336 TNF_PROBE_0(tavor_cmn_qp_mbox_fail,
2394 2337 TAVOR_TNF_ERROR, "");
2395 2338 TAVOR_TNF_EXIT(tavor_cmn_qp_cmd_post);
2396 2339 return (status);
2397 2340 }
2398 2341 in_mapaddr = mbox_info.mbi_in->mb_mapaddr;
2399 2342 out_mapaddr = 0;
2400 2343 flags = 0;
2401 2344 opmod = 0;
2402 2345
2403 2346 /* Copy the Tavor command into the "In" mailbox */
2404 2347 size = sizeof (tavor_hw_qpc_t);
2405 2348 for (i = 0; i < (size >> 3); i++) {
2406 2349 data = ((uint64_t *)qp)[i];
2407 2350 ddi_put64(mbox_info.mbi_in->mb_acchdl,
2408 2351 ((uint64_t *)mbox_info.mbi_in->mb_addr + i + 1),
2409 2352 data);
2410 2353 }
2411 2354 ddi_put32(mbox_info.mbi_in->mb_acchdl,
2412 2355 ((uint32_t *)mbox_info.mbi_in->mb_addr), opmask);
2413 2356
2414 2357 /*
2415 2358 * Sync the mailbox for the device to read. We have to add
2416 2359 * eight bytes here to account for "opt_param_mask" and
2417 2360 * proper alignment.
2418 2361 */
2419 2362 tavor_mbox_sync(mbox_info.mbi_in, 0, size + 8,
2420 2363 DDI_DMA_SYNC_FORDEV);
2421 2364 }
2422 2365
2423 2366 /* Setup and post Tavor QP state transition command */
2424 2367 cmd.cp_inparm = in_mapaddr;
2425 2368 cmd.cp_outparm = out_mapaddr;
2426 2369 cmd.cp_inmod = qpindx | flags;
2427 2370 cmd.cp_opcode = opcode;
2428 2371 cmd.cp_opmod = opmod;
2429 2372 cmd.cp_flags = sleepflag;
2430 2373 status = tavor_cmd_post(state, &cmd);
2431 2374 if (status != TAVOR_CMD_SUCCESS) {
2432 2375 TNF_PROBE_0(tavor_cmn_qp_cmd_post_fail, TAVOR_TNF_ERROR, "");
2433 2376 }
2434 2377
2435 2378 /*
2436 2379 * If we allocated a mailbox (either an "In" or an "Out") above,
2437 2380 * then free it now before returning.
2438 2381 */
2439 2382 if ((opcode != RTS2SQD_QP) && (opcode != TOERR_QP) &&
2440 2383 (opcode != TORST_QP)) {
2441 2384 /* Free the mailbox */
2442 2385 tavor_mbox_free(state, &mbox_info);
2443 2386 }
2444 2387
2445 2388 TAVOR_TNF_EXIT(tavor_cmn_qp_cmd_post);
2446 2389 return (status);
2447 2390 }
2448 2391
2449 2392
2450 2393 /*
2451 2394 * tavor_cmn_query_cmd_post()
2452 2395 * Context: Can be called from interrupt or base context.
2453 2396 *
2454 2397 * This is the common function for posting all the various types of
2455 2398 * Tavor query commands. All Tavor query commands require an "Out"
2456 2399 * mailbox to be allocated for the resulting queried data.
2457 2400 *
2458 2401 * Note: This common function should be used only with the following
2459 2402 * opcodes: QUERY_DEV_LIM, QUERY_FW, QUERY_DDR, QUERY_ADAPTER,
2460 2403 * QUERY_HCA, QUERY_MPT, QUERY_EQ, QUERY_CQ, and QUERY_QP.
2461 2404 */
2462 2405 int
2463 2406 tavor_cmn_query_cmd_post(tavor_state_t *state, uint_t opcode,
2464 2407 uint_t queryindx, void *query, uint_t size, uint_t sleepflag)
2465 2408 {
2466 2409 tavor_mbox_info_t mbox_info;
2467 2410 tavor_cmd_post_t cmd;
2468 2411 uint64_t data;
2469 2412 uint_t offset;
2470 2413 int status, i;
2471 2414
2472 2415 TAVOR_TNF_ENTER(tavor_cmn_query_cmd_post);
2473 2416
2474 2417 /* Get an "Out" mailbox for the command */
2475 2418 mbox_info.mbi_alloc_flags = TAVOR_ALLOC_OUTMBOX;
2476 2419 status = tavor_mbox_alloc(state, &mbox_info, sleepflag);
2477 2420 if (status != TAVOR_CMD_SUCCESS) {
2478 2421 TNF_PROBE_0(tavor_cmn_query_mbox_fail, TAVOR_TNF_ERROR, "");
2479 2422 TAVOR_TNF_EXIT(tavor_cmn_query_cmd_post);
2480 2423 return (status);
2481 2424 }
2482 2425
2483 2426 /* Setup and post the Tavor query command */
2484 2427 cmd.cp_inparm = 0;
2485 2428 cmd.cp_outparm = mbox_info.mbi_out->mb_mapaddr;
2486 2429 cmd.cp_inmod = queryindx;
2487 2430 cmd.cp_opcode = opcode;
2488 2431 cmd.cp_opmod = 0;
2489 2432 cmd.cp_flags = sleepflag;
2490 2433 status = tavor_cmd_post(state, &cmd);
2491 2434 if (status != TAVOR_CMD_SUCCESS) {
2492 2435 TNF_PROBE_0(tavor_cmn_query_cmd_post_fail, TAVOR_TNF_ERROR, "");
2493 2436 goto cmn_query_fail;
2494 2437 }
2495 2438
2496 2439 /* Sync the mailbox to read the results */
2497 2440 tavor_mbox_sync(mbox_info.mbi_out, 0, size, DDI_DMA_SYNC_FORCPU);
2498 2441
2499 2442 /*
2500 2443 * QUERY_QP is handled somewhat differently than the other query
2501 2444 * commands. For QUERY_QP, the actual queried data is offset into
2502 2445 * the mailbox (by one 64-bit word).
2503 2446 */
2504 2447 offset = (opcode == QUERY_QP) ? 1 : 0;
2505 2448
2506 2449 /* Copy query command results into "query" */
2507 2450 for (i = 0; i < (size >> 3); i++) {
2508 2451 data = ddi_get64(mbox_info.mbi_out->mb_acchdl,
2509 2452 ((uint64_t *)mbox_info.mbi_out->mb_addr + i + offset));
2510 2453 ((uint64_t *)query)[i] = data;
2511 2454 }
2512 2455
2513 2456 cmn_query_fail:
2514 2457 /* Free the mailbox */
2515 2458 tavor_mbox_free(state, &mbox_info);
2516 2459
2517 2460 TAVOR_TNF_EXIT(tavor_cmn_query_cmd_post);
2518 2461 return (status);
2519 2462 }
2520 2463
2521 2464
2522 2465 /*
2523 2466 * tavor_cmn_ownership_cmd_post()
2524 2467 * Context: Can be called from interrupt or base context.
2525 2468 *
2526 2469 * This is the common function for posting all the various types of
2527 2470 * Tavor HW/SW resource ownership commands. Since some of the commands
2528 2471 * differ from the others in the direction of ownership change (i.e.
2529 2472 * from HW ownership to SW, or vice versa), they differ in the type of
2530 2473 * mailbox and specific handling that each requires. This routine does
2531 2474 * certain checks based on opcode type to determine the direction of
2532 2475 * the transition and to correctly handle the request.
2533 2476 *
2534 2477 * Note: This common function should be used only with the following
2535 2478 * opcodes: HW2SW_MPT, HW2SW_EQ, HW2SW_CQ, SW2HW_MPT, SW2HW_EQ, and
2536 2479 * SW2HW_CQ
2537 2480 */
2538 2481 int
2539 2482 tavor_cmn_ownership_cmd_post(tavor_state_t *state, uint_t opcode,
2540 2483 void *hwrsrc, uint_t size, uint_t hwrsrcindx, uint_t sleepflag)
2541 2484 {
2542 2485 tavor_mbox_info_t mbox_info;
2543 2486 tavor_cmd_post_t cmd;
2544 2487 uint64_t data, in_mapaddr, out_mapaddr;
2545 2488 uint_t direction, opmod;
2546 2489 int status, i;
2547 2490
2548 2491 TAVOR_TNF_ENTER(tavor_cmn_ownership_cmd_post);
2549 2492
2550 2493 /*
2551 2494 * Determine the direction of the ownership transfer based on the
2552 2495 * provided opcode
2553 2496 */
2554 2497 if ((opcode == HW2SW_MPT) || (opcode == HW2SW_EQ) ||
2555 2498 (opcode == HW2SW_CQ) || (opcode == HW2SW_SRQ)) {
2556 2499 direction = TAVOR_CMD_RSRC_HW2SW;
2557 2500
2558 2501 } else if ((opcode == SW2HW_MPT) || (opcode == SW2HW_EQ) ||
2559 2502 (opcode == SW2HW_CQ) || (opcode == SW2HW_SRQ)) {
2560 2503 direction = TAVOR_CMD_RSRC_SW2HW;
2561 2504
2562 2505 } else {
2563 2506 TNF_PROBE_0(tavor_cmn_ownership_dir_fail,
2564 2507 TAVOR_TNF_ERROR, "");
2565 2508 TAVOR_TNF_EXIT(tavor_cmn_ownership_cmd_post);
2566 2509 return (TAVOR_CMD_INVALID_STATUS);
2567 2510 }
2568 2511
2569 2512 /*
2570 2513 * If hwrsrc is NULL then we do not allocate a mailbox. This is used
2571 2514 * in the case of memory deregister where the out mailbox is not
2572 2515 * needed. In the case of re-register, we do use the hwrsrc.
2573 2516 *
2574 2517 * Otherwise, If ownership transfer is going from hardware to software,
2575 2518 * then allocate an "Out" mailbox. This will be filled in later as a
2576 2519 * result of the Tavor command.
2577 2520 *
2578 2521 * And if the ownership transfer is going from software to hardware,
2579 2522 * then we need an "In" mailbox, and we need to fill it in and sync it
2580 2523 * (if necessary). Then the mailbox can be passed to the Tavor
2581 2524 * firmware.
2582 2525 *
2583 2526 * For the HW2SW (dereg) case, we only use an out mbox if hwrsrc is !=
2584 2527 * NULL. This implies a re-reg, and the out mbox must be used. If
2585 2528 * hwrsrc is == NULL, then we can save some time and resources by not
2586 2529 * using an out mbox at all. We must set opmod to TAVOR_CMD_DO_OUTMBOX
2587 2530 * and TAVOR_CMD_NO_OUTMBOX appropriately in this case.
2588 2531 *
2589 2532 * For the SW2HW (reg) case, no out mbox is possible. We set opmod to
2590 2533 * 0 anyway, but this field is not used in this case.
2591 2534 */
2592 2535 if (direction == TAVOR_CMD_RSRC_HW2SW) {
2593 2536 if (hwrsrc != NULL) {
2594 2537 mbox_info.mbi_alloc_flags = TAVOR_ALLOC_OUTMBOX;
2595 2538 status = tavor_mbox_alloc(state, &mbox_info,
2596 2539 sleepflag);
2597 2540 if (status != TAVOR_CMD_SUCCESS) {
2598 2541 TNF_PROBE_0(tavor_cmn_ownership_mbox_fail,
2599 2542 TAVOR_TNF_ERROR, "");
2600 2543 TAVOR_TNF_EXIT(tavor_cmn_ownership_cmd_post);
2601 2544 return (status);
2602 2545 }
2603 2546 in_mapaddr = 0;
2604 2547 out_mapaddr = mbox_info.mbi_out->mb_mapaddr;
2605 2548 opmod = TAVOR_CMD_DO_OUTMBOX;
2606 2549 } else {
2607 2550 in_mapaddr = 0;
2608 2551 out_mapaddr = 0;
2609 2552 opmod = TAVOR_CMD_NO_OUTMBOX;
2610 2553 }
2611 2554 } else { /* TAVOR_CMD_RSRC_SW2HW */
2612 2555 mbox_info.mbi_alloc_flags = TAVOR_ALLOC_INMBOX;
2613 2556 status = tavor_mbox_alloc(state, &mbox_info, sleepflag);
2614 2557 if (status != TAVOR_CMD_SUCCESS) {
2615 2558 TNF_PROBE_0(tavor_cmn_ownership_mbox_fail,
2616 2559 TAVOR_TNF_ERROR, "");
2617 2560 TAVOR_TNF_EXIT(tavor_sw2hw_mpt_cmd_post);
2618 2561 return (status);
2619 2562 }
2620 2563
2621 2564 /* Copy the SW2HW ownership command into mailbox */
2622 2565 for (i = 0; i < (size >> 3); i++) {
2623 2566 data = ((uint64_t *)hwrsrc)[i];
2624 2567 ddi_put64(mbox_info.mbi_in->mb_acchdl,
2625 2568 ((uint64_t *)mbox_info.mbi_in->mb_addr + i),
2626 2569 data);
2627 2570 }
2628 2571
2629 2572 /* Sync the mailbox for the device to read */
2630 2573 tavor_mbox_sync(mbox_info.mbi_in, 0, size,
2631 2574 DDI_DMA_SYNC_FORDEV);
2632 2575
2633 2576 in_mapaddr = mbox_info.mbi_in->mb_mapaddr;
2634 2577 out_mapaddr = 0;
2635 2578 opmod = 0;
2636 2579 }
2637 2580
2638 2581
2639 2582 /* Setup and post the Tavor ownership command */
2640 2583 cmd.cp_inparm = in_mapaddr;
2641 2584 cmd.cp_outparm = out_mapaddr;
2642 2585 cmd.cp_inmod = hwrsrcindx;
2643 2586 cmd.cp_opcode = opcode;
2644 2587 cmd.cp_opmod = opmod;
2645 2588 cmd.cp_flags = sleepflag;
2646 2589 status = tavor_cmd_post(state, &cmd);
2647 2590 if (status != TAVOR_CMD_SUCCESS) {
2648 2591 TNF_PROBE_0(tavor_cmn_ownership_cmd_post_fail,
2649 2592 TAVOR_TNF_ERROR, "");
2650 2593 goto cmn_ownership_fail;
2651 2594 }
2652 2595
2653 2596 /*
2654 2597 * As mentioned above, for HW2SW ownership transfers we need to
2655 2598 * sync (if necessary) and copy out the resulting data from the
2656 2599 * "Out" mailbox" (assuming the above command was successful).
2657 2600 */
2658 2601 if (direction == TAVOR_CMD_RSRC_HW2SW && hwrsrc != NULL) {
2659 2602 /* Sync the mailbox to read the results */
2660 2603 tavor_mbox_sync(mbox_info.mbi_out, 0, size,
2661 2604 DDI_DMA_SYNC_FORCPU);
2662 2605
2663 2606 /* Copy HW2SW ownership command results into "hwrsrc" */
2664 2607 for (i = 0; i < (size >> 3); i++) {
2665 2608 data = ddi_get64(mbox_info.mbi_out->mb_acchdl,
2666 2609 ((uint64_t *)mbox_info.mbi_out->mb_addr + i));
2667 2610 ((uint64_t *)hwrsrc)[i] = data;
2668 2611 }
2669 2612 }
2670 2613
2671 2614 cmn_ownership_fail:
2672 2615 if (hwrsrc != NULL) {
2673 2616 /* Free the mailbox */
2674 2617 tavor_mbox_free(state, &mbox_info);
2675 2618 }
2676 2619
2677 2620 TAVOR_TNF_EXIT(tavor_cmn_ownership_cmd_post);
2678 2621 return (status);
2679 2622 }
2680 2623
2681 2624
2682 2625 /*
2683 2626 * tavor_conf_special_qp_cmd_post()
2684 2627 * Context: Can be called from interrupt or base context.
2685 2628 */
2686 2629 int
2687 2630 tavor_conf_special_qp_cmd_post(tavor_state_t *state, uint_t qpindx,
2688 2631 uint_t qptype, uint_t sleepflag)
2689 2632 {
2690 2633 tavor_cmd_post_t cmd;
2691 2634 int status;
2692 2635
2693 2636 TAVOR_TNF_ENTER(tavor_conf_special_qp_cmd_post);
2694 2637
2695 2638 /* Setup and post Tavor "CONF_SPECIAL_QP" command */
2696 2639 cmd.cp_inparm = 0;
2697 2640 cmd.cp_outparm = 0;
2698 2641 cmd.cp_inmod = qpindx;
2699 2642 cmd.cp_opcode = CONF_SPECIAL_QP;
2700 2643 cmd.cp_opmod = qptype;
2701 2644 cmd.cp_flags = sleepflag;
2702 2645 status = tavor_cmd_post(state, &cmd);
2703 2646 if (status != TAVOR_CMD_SUCCESS) {
2704 2647 TNF_PROBE_0(tavor_conf_special_qp_cmd_post_fail,
2705 2648 TAVOR_TNF_ERROR, "");
2706 2649 }
2707 2650
2708 2651 TAVOR_TNF_EXIT(tavor_conf_special_qp_cmd_post);
2709 2652 return (status);
2710 2653 }
2711 2654
2712 2655
2713 2656 /*
2714 2657 * tavor_mgid_hash_cmd_post()
2715 2658 * Context: Can be called from interrupt or base context.
2716 2659 */
2717 2660 int
2718 2661 tavor_mgid_hash_cmd_post(tavor_state_t *state, uint64_t mgid_h,
2719 2662 uint64_t mgid_l, uint64_t *mgid_hash, uint_t sleepflag)
2720 2663 {
2721 2664 tavor_mbox_info_t mbox_info;
2722 2665 tavor_cmd_post_t cmd;
2723 2666 int status;
2724 2667
2725 2668 TAVOR_TNF_ENTER(tavor_mgid_hash_cmd_post);
2726 2669
2727 2670 /* Get an "In" mailbox for the command */
2728 2671 mbox_info.mbi_alloc_flags = TAVOR_ALLOC_INMBOX;
2729 2672 status = tavor_mbox_alloc(state, &mbox_info, sleepflag);
2730 2673 if (status != TAVOR_CMD_SUCCESS) {
2731 2674 TNF_PROBE_0(tavor_mgid_hash_mbox_fail, TAVOR_TNF_ERROR, "");
2732 2675 TAVOR_TNF_EXIT(tavor_mgid_hash_cmd_post);
2733 2676 return (status);
2734 2677 }
2735 2678
2736 2679 /* Copy the Tavor "MGID_HASH" command into mailbox */
2737 2680 ddi_put64(mbox_info.mbi_in->mb_acchdl,
2738 2681 ((uint64_t *)mbox_info.mbi_in->mb_addr + 0), mgid_h);
2739 2682 ddi_put64(mbox_info.mbi_in->mb_acchdl,
2740 2683 ((uint64_t *)mbox_info.mbi_in->mb_addr + 1), mgid_l);
2741 2684
2742 2685 /* Sync the mailbox for the device to read */
2743 2686 tavor_mbox_sync(mbox_info.mbi_in, 0, TAVOR_CMD_MGIDHASH_SZ,
2744 2687 DDI_DMA_SYNC_FORDEV);
2745 2688
2746 2689 /* Setup and post the Tavor "MGID_HASH" command */
2747 2690 cmd.cp_inparm = mbox_info.mbi_in->mb_mapaddr;
2748 2691 cmd.cp_outparm = 0;
2749 2692 cmd.cp_inmod = 0;
2750 2693 cmd.cp_opcode = MGID_HASH;
2751 2694 cmd.cp_opmod = 0;
2752 2695 cmd.cp_flags = sleepflag;
2753 2696 status = tavor_cmd_post(state, &cmd);
2754 2697 if (status != TAVOR_CMD_SUCCESS) {
2755 2698 TNF_PROBE_0(tavor_mgid_hash_cmd_post_fail, TAVOR_TNF_ERROR, "");
2756 2699 }
2757 2700
2758 2701 /* MGID hash value is returned in command "outparam" */
2759 2702 *mgid_hash = cmd.cp_outparm;
2760 2703
2761 2704 /* Free the mailbox */
2762 2705 tavor_mbox_free(state, &mbox_info);
2763 2706
2764 2707 TAVOR_TNF_EXIT(tavor_mgid_hash_cmd_post);
2765 2708 return (status);
2766 2709 }
2767 2710
2768 2711
2769 2712 /*
2770 2713 * tavor_read_mgm_cmd_post()
2771 2714 * Context: Can be called from interrupt or base context.
2772 2715 *
2773 2716 * Note: It is assumed that the "mcg" parameter is actually a pointer to a
2774 2717 * "tavor_hw_mcg_t" struct and some number of "tavor_hw_mcg_qp_list_t"
2775 2718 * structs. Combined size should be equal to result of TAVOR_MCGMEM_SZ()
2776 2719 * macro.
2777 2720 */
2778 2721 int
2779 2722 tavor_read_mgm_cmd_post(tavor_state_t *state, tavor_hw_mcg_t *mcg,
2780 2723 uint_t mcgindx, uint_t sleepflag)
2781 2724 {
2782 2725 tavor_mbox_info_t mbox_info;
2783 2726 tavor_cmd_post_t cmd;
2784 2727 uint64_t data;
2785 2728 uint_t size, hdrsz, qplistsz;
2786 2729 int status, i;
2787 2730
2788 2731 TAVOR_TNF_ENTER(tavor_read_mgm_cmd_post);
2789 2732
2790 2733 /* Get an "Out" mailbox for the results */
2791 2734 mbox_info.mbi_alloc_flags = TAVOR_ALLOC_OUTMBOX;
2792 2735 status = tavor_mbox_alloc(state, &mbox_info, sleepflag);
2793 2736 if (status != TAVOR_CMD_SUCCESS) {
2794 2737 TNF_PROBE_0(tavor_read_mgm_mbox_fail, TAVOR_TNF_ERROR, "");
2795 2738 TAVOR_TNF_EXIT(tavor_read_mgm_cmd_post);
2796 2739 return (status);
2797 2740 }
2798 2741
2799 2742 /* Setup and post Tavor "READ_MGM" command */
2800 2743 cmd.cp_inparm = 0;
2801 2744 cmd.cp_outparm = mbox_info.mbi_out->mb_mapaddr;
2802 2745 cmd.cp_inmod = mcgindx;
2803 2746 cmd.cp_opcode = READ_MGM;
2804 2747 cmd.cp_opmod = 0;
2805 2748 cmd.cp_flags = sleepflag;
2806 2749 status = tavor_cmd_post(state, &cmd);
2807 2750 if (status != TAVOR_CMD_SUCCESS) {
2808 2751 TNF_PROBE_0(tavor_read_mgm_cmd_post_fail, TAVOR_TNF_ERROR, "");
2809 2752 goto read_mgm_fail;
2810 2753 }
2811 2754
2812 2755 /* Sync the mailbox to read the results */
2813 2756 size = TAVOR_MCGMEM_SZ(state);
2814 2757 tavor_mbox_sync(mbox_info.mbi_out, 0, size, DDI_DMA_SYNC_FORCPU);
2815 2758
2816 2759 /* Copy the READ_MGM command results into "mcg" */
2817 2760 hdrsz = sizeof (tavor_hw_mcg_t);
2818 2761 for (i = 0; i < (hdrsz >> 3); i++) {
2819 2762 data = ddi_get64(mbox_info.mbi_out->mb_acchdl,
2820 2763 ((uint64_t *)mbox_info.mbi_out->mb_addr + i));
2821 2764 ((uint64_t *)mcg)[i] = data;
2822 2765 }
2823 2766 qplistsz = size - hdrsz;
2824 2767 for (i = 0; i < (qplistsz >> 2); i++) {
2825 2768 data = ddi_get32(mbox_info.mbi_out->mb_acchdl,
2826 2769 ((uint32_t *)mbox_info.mbi_out->mb_addr + i + 8));
2827 2770 ((uint32_t *)mcg)[i + 8] = data;
2828 2771 }
2829 2772
2830 2773 read_mgm_fail:
2831 2774 /* Free the mailbox */
2832 2775 tavor_mbox_free(state, &mbox_info);
2833 2776
2834 2777 TAVOR_TNF_EXIT(tavor_read_mgm_cmd_post);
2835 2778 return (status);
2836 2779 }
2837 2780
2838 2781
2839 2782 /*
2840 2783 * tavor_write_mgm_cmd_post()
2841 2784 * Context: Can be called from interrupt or base context.
2842 2785 *
2843 2786 * Note: It is assumed that the "mcg" parameter is actually a pointer to a
2844 2787 * "tavor_hw_mcg_t" struct and some number of "tavor_hw_mcg_qp_list_t"
2845 2788 * structs. Combined size should be equal to result of TAVOR_MCGMEM_SZ()
2846 2789 * macro.
2847 2790 */
2848 2791 int
2849 2792 tavor_write_mgm_cmd_post(tavor_state_t *state, tavor_hw_mcg_t *mcg,
2850 2793 uint_t mcgindx, uint_t sleepflag)
2851 2794 {
2852 2795 tavor_mbox_info_t mbox_info;
2853 2796 tavor_cmd_post_t cmd;
2854 2797 uint64_t data;
2855 2798 uint_t size, hdrsz, qplistsz;
2856 2799 int status, i;
2857 2800
2858 2801 TAVOR_TNF_ENTER(tavor_write_mgm_cmd_post);
2859 2802
2860 2803 /* Get an "In" mailbox for the command */
2861 2804 mbox_info.mbi_alloc_flags = TAVOR_ALLOC_INMBOX;
2862 2805 status = tavor_mbox_alloc(state, &mbox_info, sleepflag);
2863 2806 if (status != TAVOR_CMD_SUCCESS) {
2864 2807 TNF_PROBE_0(tavor_write_mcg_mbox_fail, TAVOR_TNF_ERROR, "");
2865 2808 TAVOR_TNF_EXIT(tavor_write_mgm_cmd_post);
2866 2809 return (status);
2867 2810 }
2868 2811
2869 2812 /* Copy the Tavor "WRITE_MGM" command into mailbox */
2870 2813 size = TAVOR_MCGMEM_SZ(state);
2871 2814 hdrsz = sizeof (tavor_hw_mcg_t);
2872 2815 for (i = 0; i < (hdrsz >> 3); i++) {
2873 2816 data = ((uint64_t *)mcg)[i];
2874 2817 ddi_put64(mbox_info.mbi_in->mb_acchdl,
2875 2818 ((uint64_t *)mbox_info.mbi_in->mb_addr + i), data);
2876 2819 }
2877 2820 qplistsz = size - hdrsz;
2878 2821 for (i = 0; i < (qplistsz >> 2); i++) {
2879 2822 data = ((uint32_t *)mcg)[i + 8];
2880 2823 ddi_put32(mbox_info.mbi_in->mb_acchdl,
2881 2824 ((uint32_t *)mbox_info.mbi_in->mb_addr + i + 8), data);
2882 2825 }
2883 2826
2884 2827 /* Sync the mailbox for the device to read */
2885 2828 tavor_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
2886 2829
2887 2830 /* Setup and post Tavor "WRITE_MGM" command */
2888 2831 cmd.cp_inparm = mbox_info.mbi_in->mb_mapaddr;
2889 2832 cmd.cp_outparm = 0;
2890 2833 cmd.cp_inmod = mcgindx;
2891 2834 cmd.cp_opcode = WRITE_MGM;
2892 2835 cmd.cp_opmod = 0;
2893 2836 cmd.cp_flags = sleepflag;
2894 2837 status = tavor_cmd_post(state, &cmd);
2895 2838 if (status != TAVOR_CMD_SUCCESS) {
2896 2839 TNF_PROBE_0(tavor_write_mgm_cmd_post_fail, TAVOR_TNF_ERROR, "");
2897 2840 }
2898 2841
2899 2842 /* Free the mailbox */
2900 2843 tavor_mbox_free(state, &mbox_info);
2901 2844
2902 2845 TAVOR_TNF_EXIT(tavor_write_mgm_cmd_post);
2903 2846 return (status);
2904 2847
2905 2848 }
2906 2849
2907 2850
2908 2851 /*
2909 2852 * tavor_modify_mpt_cmd_post()
2910 2853 * Context: Can be called from interrupt or base context.
2911 2854 */
2912 2855 int
2913 2856 tavor_modify_mpt_cmd_post(tavor_state_t *state, tavor_hw_mpt_t *mpt,
2914 2857 uint_t mptindx, uint_t flags, uint_t sleepflag)
2915 2858 {
2916 2859 tavor_mbox_info_t mbox_info;
2917 2860 tavor_cmd_post_t cmd;
2918 2861 uint64_t data;
2919 2862 uint_t size;
2920 2863 int status, i;
2921 2864
2922 2865 TAVOR_TNF_ENTER(tavor_modify_mpt_cmd_post);
2923 2866
2924 2867 /* Get an "In" mailbox for the command */
2925 2868 mbox_info.mbi_alloc_flags = TAVOR_ALLOC_INMBOX;
2926 2869 status = tavor_mbox_alloc(state, &mbox_info, sleepflag);
2927 2870 if (status != TAVOR_CMD_SUCCESS) {
2928 2871 TNF_PROBE_0(tavor_modify_mpt_mbox_fail, TAVOR_TNF_ERROR, "");
2929 2872 TAVOR_TNF_EXIT(tavor_modify_mpt_cmd_post);
2930 2873 return (status);
2931 2874 }
2932 2875
2933 2876 /* Copy the Tavor "MODIFY_MPT" command into mailbox */
2934 2877 size = sizeof (tavor_hw_mpt_t);
2935 2878 for (i = 0; i < (size >> 3); i++) {
2936 2879 data = ((uint64_t *)mpt)[i];
2937 2880 ddi_put64(mbox_info.mbi_in->mb_acchdl,
2938 2881 ((uint64_t *)mbox_info.mbi_in->mb_addr + i), data);
2939 2882 }
2940 2883
2941 2884 /* Sync the mailbox for the device to read */
2942 2885 tavor_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
2943 2886
2944 2887 /* Setup and post Tavor "MODIFY_MPT" command */
2945 2888 cmd.cp_inparm = mbox_info.mbi_in->mb_mapaddr;
2946 2889 cmd.cp_outparm = 0;
2947 2890 cmd.cp_inmod = mptindx;
2948 2891 cmd.cp_opcode = MODIFY_MPT;
2949 2892 cmd.cp_opmod = flags;
2950 2893 cmd.cp_flags = sleepflag;
2951 2894 status = tavor_cmd_post(state, &cmd);
2952 2895 if (status != TAVOR_CMD_SUCCESS) {
2953 2896 TNF_PROBE_0(tavor_modify_mpt_cmd_post_fail,
2954 2897 TAVOR_TNF_ERROR, "");
2955 2898 }
2956 2899
2957 2900 /* Free the mailbox */
2958 2901 tavor_mbox_free(state, &mbox_info);
2959 2902
2960 2903 TAVOR_TNF_EXIT(tavor_modify_mpt_cmd_post);
2961 2904 return (status);
2962 2905 }
2963 2906
2964 2907 /*
2965 2908 * tavor_getpefcntr_cmd_post()
2966 2909 * Context: Can be called from interrupt or base context.
2967 2910 *
2968 2911 * If reset is zero, read the performance counters of the specified port and
2969 2912 * copy them into perfinfo.
2970 2913 * If reset is non-zero reset the performance counters of the specified port.
2971 2914 */
2972 2915 int
2973 2916 tavor_getperfcntr_cmd_post(tavor_state_t *state, uint_t port,
2974 2917 uint_t sleepflag, tavor_hw_sm_perfcntr_t *perfinfo, int reset)
2975 2918 {
2976 2919 tavor_mbox_info_t mbox_info;
2977 2920 tavor_cmd_post_t cmd;
2978 2921 uint64_t data;
2979 2922 uint32_t *mbox;
2980 2923 uint_t size;
2981 2924 int status, i;
2982 2925
2983 2926 bzero((void *)&cmd, sizeof (tavor_cmd_post_t));
2984 2927
2985 2928 /* Get "In" and "Out" mailboxes for the command */
2986 2929 mbox_info.mbi_alloc_flags = TAVOR_ALLOC_INMBOX | TAVOR_ALLOC_OUTMBOX;
2987 2930 status = tavor_mbox_alloc(state, &mbox_info, sleepflag);
2988 2931 if (status != TAVOR_CMD_SUCCESS) {
2989 2932 return (status);
2990 2933 }
2991 2934
2992 2935 /* Build request MAD in the "In" mailbox */
2993 2936 size = TAVOR_CMD_MAD_IFC_SIZE;
2994 2937 mbox = (uint32_t *)mbox_info.mbi_in->mb_addr;
2995 2938
2996 2939 if (reset) {
2997 2940 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[0],
2998 2941 TAVOR_CMD_PERF_SET);
2999 2942 } else {
3000 2943 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[0],
3001 2944 TAVOR_CMD_PERF_GET);
3002 2945 }
3003 2946 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[1], TAVOR_CMD_MADHDR1);
3004 2947 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[2], TAVOR_CMD_MADHDR2);
3005 2948 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[3], TAVOR_CMD_MADHDR3);
3006 2949 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[4], TAVOR_CMD_PERFCNTRS);
3007 2950 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[5], TAVOR_CMD_PERFATTR);
3008 2951
3009 2952 if (reset) {
3010 2953 /* reset counters for XmitData, RcvData, XmitPkts, RcvPkts */
3011 2954 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[16],
3012 2955 ((port << 16) | 0xf000));
3013 2956
3014 2957 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[22], 0);
3015 2958 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[23], 0);
3016 2959 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[24], 0);
3017 2960 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[25], 0);
3018 2961 } else
3019 2962 ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[16], (port << 16));
3020 2963
3021 2964 /* Sync the mailbox for the device to read */
3022 2965 tavor_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
3023 2966
3024 2967 /* Setup the Hermon "MAD_IFC" command */
3025 2968 cmd.cp_inparm = mbox_info.mbi_in->mb_mapaddr;
3026 2969 cmd.cp_outparm = mbox_info.mbi_out->mb_mapaddr;
3027 2970 cmd.cp_inmod = port;
3028 2971 cmd.cp_opcode = MAD_IFC;
3029 2972 /* No MKey and BKey checking */
3030 2973 cmd.cp_opmod = TAVOR_CMD_MKEY_DONTCHECK | TAVOR_CMD_BKEY_DONTCHECK;
3031 2974 cmd.cp_flags = TAVOR_CMD_NOSLEEP_SPIN; /* NO SLEEP */
3032 2975 status = tavor_cmd_post(state, &cmd);
3033 2976 if (status != TAVOR_CMD_SUCCESS) {
3034 2977 goto getperfinfo_fail;
3035 2978 }
3036 2979
3037 2980 /* Sync the mailbox to read the results */
3038 2981 size = TAVOR_CMD_MAD_IFC_SIZE;
3039 2982 tavor_mbox_sync(mbox_info.mbi_out, 0, size, DDI_DMA_SYNC_FORCPU);
3040 2983
3041 2984 if (reset == 0) {
3042 2985 size = sizeof (tavor_hw_sm_perfcntr_t); /* for the copy */
3043 2986 /*
3044 2987 * Copy Perfcounters into "perfinfo". We can discard the MAD
3045 2988 * header and the 8 Quadword reserved area of the PERM mgmt
3046 2989 * class MAD
3047 2990 */
3048 2991
3049 2992 for (i = 0; i < size >> 3; i++) {
3050 2993 data = ddi_get64(mbox_info.mbi_out->mb_acchdl,
3051 2994 ((uint64_t *)mbox_info.mbi_out->mb_addr + i + 8));
3052 2995 ((uint64_t *)(void *)perfinfo)[i] = data;
3053 2996 }
3054 2997 }
3055 2998
3056 2999 getperfinfo_fail:
3057 3000 /* Free the mailbox */
3058 3001 tavor_mbox_free(state, &mbox_info);
3059 3002 return (status);
3060 3003 }
↓ open down ↓ |
924 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX