1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * tavor_rsrc.c
29 * Tavor Resource Management Routines
30 *
31 * Implements all the routines necessary for setup, teardown, and
32 * alloc/free of all Tavor resources, including those that are managed
33 * by Tavor hardware or which live in Tavor's direct attached DDR memory.
34 */
35
36 #include <sys/types.h>
37 #include <sys/conf.h>
38 #include <sys/ddi.h>
39 #include <sys/sunddi.h>
40 #include <sys/modctl.h>
41 #include <sys/vmem.h>
42 #include <sys/bitmap.h>
43
44 #include <sys/ib/adapters/tavor/tavor.h>
45
46 /*
47 * The following routines are used for initializing and destroying
48 * the resource pools used by the Tavor resource allocation routines.
49 * They consist of four classes of object:
50 *
51 * Mailboxes: The "In" and "Out" mailbox types are used by the Tavor
52 * command interface routines. Mailboxes are used to pass information
53 * back and forth to the Tavor firmware. Either type of mailbox may
54 * be allocated from Tavor's direct attached DDR memory or from system
55 * memory (although currently all "In" mailboxes are in DDR and all "out"
56 * mailboxes come from system memory.
57 *
58 * HW entry objects: These objects represent resources required by the Tavor
59 * hardware. These objects include things like Queue Pair contexts (QPC),
60 * Completion Queue contexts (CQC), Event Queue contexts (EQC), RDB (for
61 * supporting RDMA Read/Atomic), Multicast Group entries (MCG), Memory
62 * Protection Table entries (MPT), Memory Translation Table entries (MTT).
63 *
64 * What these objects all have in common is that they are each required
65 * to come from DDR memory, they are always allocated from tables, and
66 * they are not to be directly accessed (read or written) by driver
67 * software.
68 * One notable exceptions to this rule are the Extended QP contexts (EQPC),
69 * and the UAR scratch area (UAR_SCR), both of which are not directly
70 * accessible through the Tavor resource allocation routines, but both
71 * of which are also required to reside in DDR memory and are not to be
72 * manipulated by driver software (they are privately managed by Tavor
73 * hardware).
74 * The other notable exceptions are the UAR pages (UAR_PG) which are
75 * allocated from the UAR address space rather than DDR, and the UD
76 * address vectors (UDAV) which are similar to the common object types
77 * with the major difference being that UDAVs _are_ directly read and
78 * written by driver software.
79 *
80 * SW handle objects: These objects represent resources required by Tavor
81 * driver software. They are primarily software tracking structures,
82 * which are allocated from system memory (using kmem_cache). Several of
83 * the objects have both a "constructor" and "destructor" method
84 * associated with them (see below).
85 *
86 * Protection Domain (PD) handle objects: These objects are very much like
87 * a SW handle object with the notable difference that all PD handle
88 * objects have an actual Protection Domain number (PD) associated with
89 * them (and the PD number is allocated/managed through a separate
90 * vmem_arena specifically set aside for this purpose.
91 */
92
93 static int tavor_rsrc_mbox_init(tavor_state_t *state,
94 tavor_rsrc_mbox_info_t *info);
95 static void tavor_rsrc_mbox_fini(tavor_state_t *state,
96 tavor_rsrc_mbox_info_t *info);
97
98 static int tavor_rsrc_hw_entries_init(tavor_state_t *state,
99 tavor_rsrc_hw_entry_info_t *info);
100 static void tavor_rsrc_hw_entries_fini(tavor_state_t *state,
101 tavor_rsrc_hw_entry_info_t *info);
102
103 static int tavor_rsrc_sw_handles_init(tavor_state_t *state,
104 tavor_rsrc_sw_hdl_info_t *info);
105 static void tavor_rsrc_sw_handles_fini(tavor_state_t *state,
106 tavor_rsrc_sw_hdl_info_t *info);
107
108 static int tavor_rsrc_pd_handles_init(tavor_state_t *state,
109 tavor_rsrc_sw_hdl_info_t *info);
110 static void tavor_rsrc_pd_handles_fini(tavor_state_t *state,
111 tavor_rsrc_sw_hdl_info_t *info);
112
113 /*
114 * The following routines are used for allocating and freeing the specific
115 * types of objects described above from their associated resource pools.
116 */
117 static int tavor_rsrc_mbox_alloc(tavor_rsrc_pool_info_t *pool_info,
118 uint_t num, tavor_rsrc_t *hdl);
119 static void tavor_rsrc_mbox_free(tavor_rsrc_pool_info_t *pool_info,
120 tavor_rsrc_t *hdl);
121
122 static int tavor_rsrc_hw_entry_alloc(tavor_rsrc_pool_info_t *pool_info,
123 uint_t num, uint_t num_align, ddi_acc_handle_t acc_handle,
124 uint_t sleepflag, tavor_rsrc_t *hdl);
125 static void tavor_rsrc_hw_entry_free(tavor_rsrc_pool_info_t *pool_info,
126 tavor_rsrc_t *hdl);
127
128 static int tavor_rsrc_swhdl_alloc(tavor_rsrc_pool_info_t *pool_info,
129 uint_t sleepflag, tavor_rsrc_t *hdl);
130 static void tavor_rsrc_swhdl_free(tavor_rsrc_pool_info_t *pool_info,
131 tavor_rsrc_t *hdl);
132
133 static int tavor_rsrc_pdhdl_alloc(tavor_rsrc_pool_info_t *pool_info,
134 uint_t sleepflag, tavor_rsrc_t *hdl);
135 static void tavor_rsrc_pdhdl_free(tavor_rsrc_pool_info_t *pool_info,
136 tavor_rsrc_t *hdl);
137
138 /*
139 * The following routines are the constructors and destructors for several
140 * of the SW handle type objects. For certain types of SW handles objects
141 * (all of which are implemented using kmem_cache), we need to do some
142 * special field initialization (specifically, mutex_init/destroy). These
143 * routines enable that init and teardown.
144 */
145 static int tavor_rsrc_pdhdl_constructor(void *pd, void *priv, int flags);
146 static void tavor_rsrc_pdhdl_destructor(void *pd, void *state);
147 static int tavor_rsrc_cqhdl_constructor(void *cq, void *priv, int flags);
148 static void tavor_rsrc_cqhdl_destructor(void *cq, void *state);
149 static int tavor_rsrc_qphdl_constructor(void *cq, void *priv, int flags);
150 static void tavor_rsrc_qphdl_destructor(void *cq, void *state);
151 static int tavor_rsrc_srqhdl_constructor(void *srq, void *priv, int flags);
152 static void tavor_rsrc_srqhdl_destructor(void *srq, void *state);
153 static int tavor_rsrc_refcnt_constructor(void *rc, void *priv, int flags);
154 static void tavor_rsrc_refcnt_destructor(void *rc, void *state);
155 static int tavor_rsrc_ahhdl_constructor(void *ah, void *priv, int flags);
156 static void tavor_rsrc_ahhdl_destructor(void *ah, void *state);
157 static int tavor_rsrc_mrhdl_constructor(void *mr, void *priv, int flags);
158 static void tavor_rsrc_mrhdl_destructor(void *mr, void *state);
159
160 /*
161 * Special routine to calculate and return the size of a MCG object based
162 * on current driver configuration (specifically, the number of QP per MCG
163 * that has been configured.
164 */
165 static int tavor_rsrc_mcg_entry_get_size(tavor_state_t *state,
166 uint_t *mcg_size_shift);
167
168
169 /*
170 * tavor_rsrc_alloc()
171 *
172 * Context: Can be called from interrupt or base context.
173 * The "sleepflag" parameter is used by all object allocators to
174 * determine whether to SLEEP for resources or not.
175 */
176 int
tavor_rsrc_alloc(tavor_state_t * state,tavor_rsrc_type_t rsrc,uint_t num,uint_t sleepflag,tavor_rsrc_t ** hdl)177 tavor_rsrc_alloc(tavor_state_t *state, tavor_rsrc_type_t rsrc, uint_t num,
178 uint_t sleepflag, tavor_rsrc_t **hdl)
179 {
180 tavor_rsrc_pool_info_t *rsrc_pool;
181 tavor_rsrc_t *tmp_rsrc_hdl;
182 int flag, status = DDI_FAILURE;
183
184 TAVOR_TNF_ENTER(tavor_rsrc_alloc);
185
186 ASSERT(state != NULL);
187 ASSERT(hdl != NULL);
188
189 rsrc_pool = &state->ts_rsrc_hdl[rsrc];
190 ASSERT(rsrc_pool != NULL);
191
192 /*
193 * Allocate space for the object used to track the resource handle
194 */
195 flag = (sleepflag == TAVOR_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
196 tmp_rsrc_hdl = (tavor_rsrc_t *)kmem_cache_alloc(state->ts_rsrc_cache,
197 flag);
198 if (tmp_rsrc_hdl == NULL) {
199 TNF_PROBE_0(tavor_rsrc_alloc_kmca_fail, TAVOR_TNF_ERROR, "");
200 TAVOR_TNF_EXIT(tavor_rsrc_alloc);
201 return (DDI_FAILURE);
202 }
203 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tmp_rsrc_hdl))
204
205 /*
206 * Set rsrc_hdl type. This is later used by the tavor_rsrc_free call
207 * to know what type of resource is being freed.
208 */
209 tmp_rsrc_hdl->rsrc_type = rsrc;
210
211 /*
212 * Depending on resource type, call the appropriate alloc routine
213 */
214 switch (rsrc_pool->rsrc_type) {
215 case TAVOR_IN_MBOX:
216 case TAVOR_OUT_MBOX:
217 case TAVOR_INTR_IN_MBOX:
218 case TAVOR_INTR_OUT_MBOX:
219 status = tavor_rsrc_mbox_alloc(rsrc_pool, num, tmp_rsrc_hdl);
220 break;
221
222 case TAVOR_QPC:
223 case TAVOR_CQC:
224 case TAVOR_SRQC:
225 case TAVOR_EQC:
226 case TAVOR_RDB:
227 /*
228 * Because these objects are NOT accessed by Tavor driver
229 * software, we set the acc_handle parameter to zero. But
230 * if they are allocated in multiples, we specify here that
231 * they must be aligned on a more restrictive boundary.
232 */
233 status = tavor_rsrc_hw_entry_alloc(rsrc_pool, num, num, 0,
234 sleepflag, tmp_rsrc_hdl);
235 break;
236
237 case TAVOR_MPT:
238 /*
239 * Because these MPT objects are sometimes accessed by Tavor
240 * driver software (FMR), we set the acc_handle parameter. But
241 * if they are allocated in multiples, we specify here that
242 * they must be aligned on a more restrictive boundary.
243 */
244 status = tavor_rsrc_hw_entry_alloc(rsrc_pool, num, num,
245 state->ts_reg_ddrhdl, sleepflag, tmp_rsrc_hdl);
246 break;
247
248 case TAVOR_MCG:
249 /*
250 * Tavor MCG entries are also NOT accessed by Tavor driver
251 * software, but because MCG entries do not have the same
252 * alignnment restrictions we loosen the constraint here.
253 */
254 status = tavor_rsrc_hw_entry_alloc(rsrc_pool, num, 1, 0,
255 sleepflag, tmp_rsrc_hdl);
256 break;
257
258 case TAVOR_MTT:
259 case TAVOR_UDAV:
260 /*
261 * Because MTT segments are among the few HW resources that
262 * may be allocated in odd numbers, we specify a less
263 * restrictive alignment than for the above resources.
264 *
265 * Also because both UDAV and MTT segment objects are read
266 * and/or written by Tavor driver software, we set the
267 * acc_handle parameter to point to the ddi_acc_handle_t for
268 * the Tavor DDR memory.
269 */
270 status = tavor_rsrc_hw_entry_alloc(rsrc_pool, num, 1,
271 state->ts_reg_ddrhdl, sleepflag, tmp_rsrc_hdl);
272 break;
273
274 case TAVOR_UARPG:
275 /*
276 * Because UAR pages are written by Tavor driver software (for
277 * doorbells), we set the acc_handle parameter to point to
278 * the ddi_acc_handle_t for the Tavor UAR memory.
279 */
280 status = tavor_rsrc_hw_entry_alloc(rsrc_pool, num, 1,
281 state->ts_reg_uarhdl, sleepflag, tmp_rsrc_hdl);
282 break;
283
284 case TAVOR_MRHDL:
285 case TAVOR_EQHDL:
286 case TAVOR_CQHDL:
287 case TAVOR_SRQHDL:
288 case TAVOR_AHHDL:
289 case TAVOR_QPHDL:
290 case TAVOR_REFCNT:
291 status = tavor_rsrc_swhdl_alloc(rsrc_pool, sleepflag,
292 tmp_rsrc_hdl);
293 break;
294
295 case TAVOR_PDHDL:
296 status = tavor_rsrc_pdhdl_alloc(rsrc_pool, sleepflag,
297 tmp_rsrc_hdl);
298 break;
299
300 default:
301 TAVOR_WARNING(state, "unexpected resource type in alloc");
302 TNF_PROBE_0(tavor_rsrc_alloc_inv_rsrctype_fail,
303 TAVOR_TNF_ERROR, "");
304 break;
305 }
306
307 /*
308 * If the resource allocation failed, then free the special resource
309 * tracking structure and return failure. Otherwise return the
310 * handle for the resource tracking structure.
311 */
312 if (status != DDI_SUCCESS) {
313 kmem_cache_free(state->ts_rsrc_cache, tmp_rsrc_hdl);
314 tmp_rsrc_hdl = NULL;
315 TNF_PROBE_1(tavor_rsrc_alloc_fail, TAVOR_TNF_ERROR, "",
316 tnf_uint, rsrc_type, rsrc_pool->rsrc_type);
317 TAVOR_TNF_EXIT(tavor_rsrc_alloc);
318 return (DDI_FAILURE);
319 } else {
320 *hdl = tmp_rsrc_hdl;
321 TAVOR_TNF_EXIT(tavor_rsrc_alloc);
322 return (DDI_SUCCESS);
323 }
324 }
325
326
327 /*
328 * tavor_rsrc_free()
329 * Context: Can be called from interrupt or base context.
330 */
331 void
tavor_rsrc_free(tavor_state_t * state,tavor_rsrc_t ** hdl)332 tavor_rsrc_free(tavor_state_t *state, tavor_rsrc_t **hdl)
333 {
334 tavor_rsrc_pool_info_t *rsrc_pool;
335
336 TAVOR_TNF_ENTER(tavor_rsrc_free);
337
338 ASSERT(state != NULL);
339 ASSERT(hdl != NULL);
340
341 rsrc_pool = &state->ts_rsrc_hdl[(*hdl)->rsrc_type];
342 ASSERT(rsrc_pool != NULL);
343
344 /*
345 * Depending on resource type, call the appropriate free routine
346 */
347 switch (rsrc_pool->rsrc_type) {
348 case TAVOR_IN_MBOX:
349 case TAVOR_OUT_MBOX:
350 case TAVOR_INTR_IN_MBOX:
351 case TAVOR_INTR_OUT_MBOX:
352 tavor_rsrc_mbox_free(rsrc_pool, *hdl);
353 break;
354
355 case TAVOR_QPC:
356 case TAVOR_CQC:
357 case TAVOR_SRQC:
358 case TAVOR_EQC:
359 case TAVOR_RDB:
360 case TAVOR_MCG:
361 case TAVOR_MPT:
362 case TAVOR_MTT:
363 case TAVOR_UDAV:
364 case TAVOR_UARPG:
365 tavor_rsrc_hw_entry_free(rsrc_pool, *hdl);
366 break;
367
368 case TAVOR_MRHDL:
369 case TAVOR_EQHDL:
370 case TAVOR_CQHDL:
371 case TAVOR_SRQHDL:
372 case TAVOR_AHHDL:
373 case TAVOR_QPHDL:
374 case TAVOR_REFCNT:
375 tavor_rsrc_swhdl_free(rsrc_pool, *hdl);
376 break;
377
378 case TAVOR_PDHDL:
379 tavor_rsrc_pdhdl_free(rsrc_pool, *hdl);
380 break;
381
382 default:
383 TAVOR_WARNING(state, "unexpected resource type in free");
384 TNF_PROBE_0(tavor_rsrc_free_inv_rsrctype_fail,
385 TAVOR_TNF_ERROR, "");
386 break;
387 }
388
389 /*
390 * Free the special resource tracking structure, set the handle to
391 * NULL, and return.
392 */
393 kmem_cache_free(state->ts_rsrc_cache, *hdl);
394 *hdl = NULL;
395
396 TAVOR_TNF_EXIT(tavor_rsrc_free);
397 }
398
399
400 /*
401 * tavor_rsrc_init_phase1()
402 *
403 * Completes the first phase of Tavor resource/configuration init.
404 * This involves creating the kmem_cache for the "tavor_rsrc_t"
405 * structs, allocating the space for the resource pool handles,
406 * and setting up the "Out" mailboxes.
407 *
408 * When this function completes, the Tavor driver is ready to
409 * post the following commands which return information only in the
410 * "Out" mailbox: QUERY_DDR, QUERY_FW, QUERY_DEV_LIM, and QUERY_ADAPTER
411 * If any of these commands are to be posted at this time, they must be
412 * done so only when "spinning" (as the outstanding command list and
413 * EQ setup code has not yet run)
414 *
415 * Context: Only called from attach() path context
416 */
417 int
tavor_rsrc_init_phase1(tavor_state_t * state)418 tavor_rsrc_init_phase1(tavor_state_t *state)
419 {
420 tavor_rsrc_pool_info_t *rsrc_pool;
421 tavor_rsrc_mbox_info_t mbox_info;
422 tavor_rsrc_cleanup_level_t cleanup;
423 tavor_cfg_profile_t *cfgprof;
424 uint64_t num, size;
425 int status;
426 char *errormsg, *rsrc_name;
427
428 TAVOR_TNF_ENTER(tavor_rsrc_init_phase1);
429
430 ASSERT(state != NULL);
431
432 /* This is where Phase 1 of resource initialization begins */
433 cleanup = TAVOR_RSRC_CLEANUP_LEVEL0;
434
435 /* Build kmem cache name from Tavor instance */
436 rsrc_name = (char *)kmem_zalloc(TAVOR_RSRC_NAME_MAXLEN, KM_SLEEP);
437 TAVOR_RSRC_NAME(rsrc_name, TAVOR_RSRC_CACHE);
438
439 /*
440 * Create the kmem_cache for "tavor_rsrc_t" structures
441 * (kmem_cache_create will SLEEP until successful)
442 */
443 state->ts_rsrc_cache = kmem_cache_create(rsrc_name,
444 sizeof (tavor_rsrc_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
445
446 /*
447 * Allocate an array of tavor_rsrc_pool_info_t's (used in all
448 * subsequent resource allocations)
449 */
450 state->ts_rsrc_hdl = kmem_zalloc(TAVOR_NUM_RESOURCES *
451 sizeof (tavor_rsrc_pool_info_t), KM_SLEEP);
452
453 cfgprof = state->ts_cfg_profile;
454
455 /*
456 * Initialize the resource pool for "Out" mailboxes. Notice that
457 * the number of "Out" mailboxes, their size, and their location
458 * (DDR or system memory) is configurable. By default, however,
459 * all "Out" mailboxes are located in system memory only (because
460 * they are primarily read from and never written to)
461 */
462 num = ((uint64_t)1 << cfgprof->cp_log_num_outmbox);
463 size = ((uint64_t)1 << cfgprof->cp_log_outmbox_size);
464 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_OUT_MBOX];
465 rsrc_pool->rsrc_type = TAVOR_OUT_MBOX;
466 rsrc_pool->rsrc_loc = TAVOR_IN_SYSMEM;
467 rsrc_pool->rsrc_pool_size = (size * num);
468 rsrc_pool->rsrc_shift = cfgprof->cp_log_outmbox_size;
469 rsrc_pool->rsrc_quantum = size;
470 rsrc_pool->rsrc_align = TAVOR_MBOX_ALIGN;
471 rsrc_pool->rsrc_state = state;
472 TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_OUTMBOX_VMEM);
473 mbox_info.mbi_num = num;
474 mbox_info.mbi_size = size;
475 mbox_info.mbi_rsrcpool = rsrc_pool;
476 mbox_info.mbi_rsrcname = rsrc_name;
477 status = tavor_rsrc_mbox_init(state, &mbox_info);
478 if (status != DDI_SUCCESS) {
479 tavor_rsrc_fini(state, cleanup);
480 /* Set "status" and "errormsg" and goto failure */
481 TAVOR_TNF_FAIL(DDI_FAILURE, "out mailboxes");
482 goto rsrcinitp1_fail;
483 }
484 cleanup = TAVOR_RSRC_CLEANUP_LEVEL1;
485
486 /*
487 * Initialize the Tavor "Out" mailbox list. This step actually uses
488 * the tavor_rsrc_alloc() for TAVOR_OUT_MBOX to preallocate the
489 * "Out" mailboxes, bind them for DMA access, and arrange them into
490 * an easily accessed fast-allocation mechanism (see tavor_cmd.c
491 * for more details)
492 */
493 status = tavor_outmbox_list_init(state);
494 if (status != DDI_SUCCESS) {
495 tavor_rsrc_fini(state, cleanup);
496 /* Set "status" and "errormsg" and goto failure */
497 TAVOR_TNF_FAIL(DDI_FAILURE, "out mailbox list");
498 goto rsrcinitp1_fail;
499 }
500 cleanup = TAVOR_RSRC_CLEANUP_LEVEL2;
501
502 /*
503 * Initialize the resource pool for interrupt "Out" mailboxes. Notice
504 * that the number of interrupt "Out" mailboxes, their size, and their
505 * location (DDR or system memory) is configurable. By default,
506 * however, all interrupt "Out" mailboxes are located in system memory
507 * only (because they are primarily read from and never written to)
508 */
509 num = ((uint64_t)1 << cfgprof->cp_log_num_intr_outmbox);
510 size = ((uint64_t)1 << cfgprof->cp_log_outmbox_size);
511 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_INTR_OUT_MBOX];
512 rsrc_pool->rsrc_type = TAVOR_INTR_OUT_MBOX;
513 rsrc_pool->rsrc_loc = TAVOR_IN_SYSMEM;
514 rsrc_pool->rsrc_pool_size = (size * num);
515 rsrc_pool->rsrc_shift = cfgprof->cp_log_outmbox_size;
516 rsrc_pool->rsrc_quantum = size;
517 rsrc_pool->rsrc_align = TAVOR_MBOX_ALIGN;
518 rsrc_pool->rsrc_state = state;
519 TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_INTR_OUTMBOX_VMEM);
520 mbox_info.mbi_num = num;
521 mbox_info.mbi_size = size;
522 mbox_info.mbi_rsrcpool = rsrc_pool;
523 mbox_info.mbi_rsrcname = rsrc_name;
524 status = tavor_rsrc_mbox_init(state, &mbox_info);
525 if (status != DDI_SUCCESS) {
526 tavor_rsrc_fini(state, cleanup);
527 /* Set "status" and "errormsg" and goto failure */
528 TAVOR_TNF_FAIL(DDI_FAILURE, "out intr mailboxes");
529 goto rsrcinitp1_fail;
530 }
531 cleanup = TAVOR_RSRC_CLEANUP_LEVEL3;
532
533 /*
534 * Initialize the Tavor "Out" mailbox list. This step actually uses
535 * the tavor_rsrc_alloc() for TAVOR_OUT_MBOX to preallocate the
536 * "Out" mailboxes, bind them for DMA access, and arrange them into
537 * an easily accessed fast-allocation mechanism (see tavor_cmd.c
538 * for more details)
539 */
540 status = tavor_intr_outmbox_list_init(state);
541 if (status != DDI_SUCCESS) {
542 tavor_rsrc_fini(state, cleanup);
543 /* Set "status" and "errormsg" and goto failure */
544 TAVOR_TNF_FAIL(DDI_FAILURE, "out intr mailbox list");
545 goto rsrcinitp1_fail;
546 }
547 cleanup = TAVOR_RSRC_CLEANUP_PHASE1_COMPLETE;
548
549 kmem_free(rsrc_name, TAVOR_RSRC_NAME_MAXLEN);
550 TAVOR_TNF_EXIT(tavor_rsrc_init_phase1);
551 return (DDI_SUCCESS);
552
553 rsrcinitp1_fail:
554 kmem_free(rsrc_name, TAVOR_RSRC_NAME_MAXLEN);
555 TNF_PROBE_1(tavor_rsrc_init_phase1_fail, TAVOR_TNF_ERROR, "",
556 tnf_string, msg, errormsg);
557 TAVOR_TNF_EXIT(tavor_rsrc_init_phase1);
558 return (status);
559 }
560
561
562 /*
563 * tavor_rsrc_init_phase2()
564 * Context: Only called from attach() path context
565 */
566 int
tavor_rsrc_init_phase2(tavor_state_t * state)567 tavor_rsrc_init_phase2(tavor_state_t *state)
568 {
569 tavor_rsrc_sw_hdl_info_t hdl_info;
570 tavor_rsrc_hw_entry_info_t entry_info;
571 tavor_rsrc_mbox_info_t mbox_info;
572 tavor_rsrc_pool_info_t *rsrc_pool;
573 tavor_rsrc_cleanup_level_t cleanup;
574 tavor_cfg_profile_t *cfgprof;
575 uint64_t num, max, size, num_prealloc;
576 uint64_t ddr_size, fw_size;
577 uint_t mcg_size, mcg_size_shift;
578 uint_t uarscr_size, mttsegment_sz;
579 int status;
580 char *errormsg, *rsrc_name;
581
582 TAVOR_TNF_ENTER(tavor_rsrc_init_phase2);
583
584 ASSERT(state != NULL);
585
586 /* Phase 2 initialization begins where Phase 1 left off */
587 cleanup = TAVOR_RSRC_CLEANUP_PHASE1_COMPLETE;
588
589 /*
590 * Calculate the extent of the DDR size and portion of which that
591 * is already reserved for Tavor firmware. (Note: this information
592 * is available because the QUERY_DDR and QUERY_FW commands have
593 * been posted to Tavor firmware prior to calling this routine)
594 */
595 ddr_size = state->ts_ddr.ddr_endaddr - state->ts_ddr.ddr_baseaddr + 1;
596 fw_size = state->ts_fw.fw_endaddr - state->ts_fw.fw_baseaddr + 1;
597
598 /* Build the DDR vmem arena name from Tavor instance */
599 rsrc_name = (char *)kmem_zalloc(TAVOR_RSRC_NAME_MAXLEN, KM_SLEEP);
600 TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_VMEM);
601
602 /*
603 * Do a vmem_create for the entire DDR range (not including the
604 * portion consumed by Tavor firmware). This creates the vmem arena
605 * from which all other DDR objects (specifically, tables of HW
606 * entries) will be allocated.
607 */
608 state->ts_ddrvmem = vmem_create(rsrc_name,
609 (void *)(uintptr_t)state->ts_ddr.ddr_baseaddr, (ddr_size - fw_size),
610 sizeof (uint64_t), NULL, NULL, NULL, 0, VM_SLEEP);
611 if (state->ts_ddrvmem == NULL) {
612 tavor_rsrc_fini(state, cleanup);
613 /* Set "status" and "errormsg" and goto failure */
614 TAVOR_TNF_FAIL(DDI_FAILURE, "DDR vmem");
615 goto rsrcinitp2_fail;
616 }
617 cleanup = TAVOR_RSRC_CLEANUP_LEVEL5;
618
619 /*
620 * Initialize the resource pools for all objects that exist in
621 * Tavor DDR memory. This includes ("In") mailboxes, context tables
622 * (QPC, CQC, EQC, etc...), and other miscellaneous HW objects.
623 */
624 cfgprof = state->ts_cfg_profile;
625
626 /*
627 * Initialize the resource pool for the MPT table entries. Notice
628 * that the number of MPTs is configurable. The configured value must
629 * be less that the maximum value (obtained from the QUERY_DEV_LIM
630 * command) or the initialization will fail. Note also that a certain
631 * number of MPTs must be set aside for Tavor firmware use.
632 */
633 num = ((uint64_t)1 << cfgprof->cp_log_num_mpt);
634 max = ((uint64_t)1 << state->ts_devlim.log_max_mpt);
635 num_prealloc = ((uint64_t)1 << state->ts_devlim.log_rsvd_mpt);
636 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_MPT];
637 rsrc_pool->rsrc_type = TAVOR_MPT;
638 rsrc_pool->rsrc_loc = TAVOR_IN_DDR;
639 rsrc_pool->rsrc_pool_size = (TAVOR_MPT_SIZE * num);
640 rsrc_pool->rsrc_shift = TAVOR_MPT_SIZE_SHIFT;
641 rsrc_pool->rsrc_quantum = TAVOR_MPT_SIZE;
642 rsrc_pool->rsrc_align = (TAVOR_MPT_SIZE * num);
643 rsrc_pool->rsrc_state = state;
644 rsrc_pool->rsrc_start = NULL;
645 TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_MPT_VMEM);
646 entry_info.hwi_num = num;
647 entry_info.hwi_max = max;
648 entry_info.hwi_prealloc = num_prealloc;
649 entry_info.hwi_rsrcpool = rsrc_pool;
650 entry_info.hwi_rsrcname = rsrc_name;
651 status = tavor_rsrc_hw_entries_init(state, &entry_info);
652 if (status != DDI_SUCCESS) {
653 tavor_rsrc_fini(state, cleanup);
654 /* Set "status" and "errormsg" and goto failure */
655 TAVOR_TNF_FAIL(DDI_FAILURE, "MPT table");
656 goto rsrcinitp2_fail;
657 }
658 cleanup = TAVOR_RSRC_CLEANUP_LEVEL6;
659
660 /*
661 * Initialize the resource pool for the MTT table entries. Notice
662 * that the number of MTTs is configurable. The configured value must
663 * be less that the maximum value (obtained from the QUERY_DEV_LIM
664 * command) or the initialization will fail. Note also that a certain
665 * number of MTT segments must be set aside for Tavor firmware use.
666 */
667 mttsegment_sz = (TAVOR_MTTSEG_SIZE << TAVOR_MTT_SIZE_SHIFT);
668 num = ((uint64_t)1 << cfgprof->cp_log_num_mttseg);
669 max = ((uint64_t)1 << state->ts_devlim.log_max_mttseg);
670 num_prealloc = ((uint64_t)1 << state->ts_devlim.log_rsvd_mttseg);
671 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_MTT];
672 rsrc_pool->rsrc_type = TAVOR_MTT;
673 rsrc_pool->rsrc_loc = TAVOR_IN_DDR;
674 rsrc_pool->rsrc_pool_size = (TAVOR_MTT_SIZE * num);
675 rsrc_pool->rsrc_shift = TAVOR_MTT_SIZE_SHIFT;
676 rsrc_pool->rsrc_quantum = mttsegment_sz;
677 rsrc_pool->rsrc_align = (TAVOR_MTT_SIZE * num);
678 rsrc_pool->rsrc_state = state;
679 rsrc_pool->rsrc_start = NULL;
680 TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_MTT_VMEM);
681 entry_info.hwi_num = num;
682 entry_info.hwi_max = max;
683 entry_info.hwi_prealloc = num_prealloc;
684 entry_info.hwi_rsrcpool = rsrc_pool;
685 entry_info.hwi_rsrcname = rsrc_name;
686 status = tavor_rsrc_hw_entries_init(state, &entry_info);
687 if (status != DDI_SUCCESS) {
688 tavor_rsrc_fini(state, cleanup);
689 /* Set "status" and "errormsg" and goto failure */
690 TAVOR_TNF_FAIL(DDI_FAILURE, "MTT table");
691 goto rsrcinitp2_fail;
692 }
693 cleanup = TAVOR_RSRC_CLEANUP_LEVEL7;
694
695 /*
696 * Initialize the resource pool for the QPC table entries. Notice
697 * that the number of QPs is configurable. The configured value must
698 * be less that the maximum value (obtained from the QUERY_DEV_LIM
699 * command) or the initialization will fail. Note also that a certain
700 * number of QP contexts must be set aside for Tavor firmware use.
701 */
702 num = ((uint64_t)1 << cfgprof->cp_log_num_qp);
703 max = ((uint64_t)1 << state->ts_devlim.log_max_qp);
704 num_prealloc = ((uint64_t)1 << state->ts_devlim.log_rsvd_qp);
705 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_QPC];
706 rsrc_pool->rsrc_type = TAVOR_QPC;
707 rsrc_pool->rsrc_loc = TAVOR_IN_DDR;
708 rsrc_pool->rsrc_pool_size = (TAVOR_QPC_SIZE * num);
709 rsrc_pool->rsrc_shift = TAVOR_QPC_SIZE_SHIFT;
710 rsrc_pool->rsrc_quantum = TAVOR_QPC_SIZE;
711 rsrc_pool->rsrc_align = (TAVOR_QPC_SIZE * num);
712 rsrc_pool->rsrc_state = state;
713 rsrc_pool->rsrc_start = NULL;
714 TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_QPC_VMEM);
715 entry_info.hwi_num = num;
716 entry_info.hwi_max = max;
717 entry_info.hwi_prealloc = num_prealloc;
718 entry_info.hwi_rsrcpool = rsrc_pool;
719 entry_info.hwi_rsrcname = rsrc_name;
720 status = tavor_rsrc_hw_entries_init(state, &entry_info);
721 if (status != DDI_SUCCESS) {
722 tavor_rsrc_fini(state, cleanup);
723 /* Set "status" and "errormsg" and goto failure */
724 TAVOR_TNF_FAIL(DDI_FAILURE, "QPC table");
725 goto rsrcinitp2_fail;
726 }
727 cleanup = TAVOR_RSRC_CLEANUP_LEVEL8;
728
729 /*
730 * Initialize the resource pool for the RDB table entries. Notice
731 * that the number of RDBs is configurable. The configured value must
732 * be less that the maximum value (obtained from the QUERY_DEV_LIM
733 * command) or the initialization will fail.
734 */
735 num = ((uint64_t)1 << cfgprof->cp_log_num_rdb);
736 max = ((uint64_t)1 << state->ts_devlim.log_max_ra_glob);
737 num_prealloc = 0;
738 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_RDB];
739 rsrc_pool->rsrc_type = TAVOR_RDB;
740 rsrc_pool->rsrc_loc = TAVOR_IN_DDR;
741 rsrc_pool->rsrc_pool_size = (TAVOR_RDB_SIZE * num);
742 rsrc_pool->rsrc_shift = TAVOR_RDB_SIZE_SHIFT;
743 rsrc_pool->rsrc_quantum = TAVOR_RDB_SIZE;
744 rsrc_pool->rsrc_align = (TAVOR_RDB_SIZE * num);
745 rsrc_pool->rsrc_state = state;
746 rsrc_pool->rsrc_start = NULL;
747 TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_RDB_VMEM);
748 entry_info.hwi_num = num;
749 entry_info.hwi_max = max;
750 entry_info.hwi_prealloc = num_prealloc;
751 entry_info.hwi_rsrcpool = rsrc_pool;
752 entry_info.hwi_rsrcname = rsrc_name;
753 status = tavor_rsrc_hw_entries_init(state, &entry_info);
754 if (status != DDI_SUCCESS) {
755 tavor_rsrc_fini(state, cleanup);
756 /* Set "status" and "errormsg" and goto failure */
757 TAVOR_TNF_FAIL(DDI_FAILURE, "RDB table");
758 goto rsrcinitp2_fail;
759 }
760 cleanup = TAVOR_RSRC_CLEANUP_LEVEL9;
761
762 /*
763 * Initialize the resource pool for the CQC table entries. Notice
764 * that the number of CQs is configurable. The configured value must
765 * be less that the maximum value (obtained from the QUERY_DEV_LIM
766 * command) or the initialization will fail. Note also that a certain
767 * number of CQ contexts must be set aside for Tavor firmware use.
768 */
769 num = ((uint64_t)1 << cfgprof->cp_log_num_cq);
770 max = ((uint64_t)1 << state->ts_devlim.log_max_cq);
771 num_prealloc = ((uint64_t)1 << state->ts_devlim.log_rsvd_cq);
772 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_CQC];
773 rsrc_pool->rsrc_type = TAVOR_CQC;
774 rsrc_pool->rsrc_loc = TAVOR_IN_DDR;
775 rsrc_pool->rsrc_pool_size = (TAVOR_CQC_SIZE * num);
776 rsrc_pool->rsrc_shift = TAVOR_CQC_SIZE_SHIFT;
777 rsrc_pool->rsrc_quantum = TAVOR_CQC_SIZE;
778 rsrc_pool->rsrc_align = (TAVOR_CQC_SIZE * num);
779 rsrc_pool->rsrc_state = state;
780 rsrc_pool->rsrc_start = NULL;
781 TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_CQC_VMEM);
782 entry_info.hwi_num = num;
783 entry_info.hwi_max = max;
784 entry_info.hwi_prealloc = num_prealloc;
785 entry_info.hwi_rsrcpool = rsrc_pool;
786 entry_info.hwi_rsrcname = rsrc_name;
787 status = tavor_rsrc_hw_entries_init(state, &entry_info);
788 if (status != DDI_SUCCESS) {
789 tavor_rsrc_fini(state, cleanup);
790 /* Set "status" and "errormsg" and goto failure */
791 TAVOR_TNF_FAIL(DDI_FAILURE, "CQC table");
792 goto rsrcinitp2_fail;
793 }
794 cleanup = TAVOR_RSRC_CLEANUP_LEVEL10;
795
796 /*
797 * Initialize the resource pool for the Extended QPC table entries.
798 * Notice that the number of EQPCs must be the same as the number
799 * of QP contexts. So the initialization is constructed in a
800 * similar way as above (for TAVOR_QPC). One notable difference
801 * here, however, is that by setting the rsrc_quantum field to
802 * zero (indicating a zero-sized object) we indicate that the
803 * object is not allocatable. The EQPC table is, in fact, managed
804 * internally by the hardware and it is, therefore, unnecessary to
805 * initialize an additional vmem_arena for this type of object.
806 */
807 num = ((uint64_t)1 << cfgprof->cp_log_num_qp);
808 max = ((uint64_t)1 << state->ts_devlim.log_max_qp);
809 num_prealloc = 0;
810 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_EQPC];
811 rsrc_pool->rsrc_type = TAVOR_EQPC;
812 rsrc_pool->rsrc_loc = TAVOR_IN_DDR;
813 rsrc_pool->rsrc_pool_size = (TAVOR_EQPC_SIZE * num);
814 rsrc_pool->rsrc_shift = 0;
815 rsrc_pool->rsrc_quantum = 0;
816 rsrc_pool->rsrc_align = TAVOR_EQPC_SIZE;
817 rsrc_pool->rsrc_state = state;
818 rsrc_pool->rsrc_start = NULL;
819 TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_EQPC_VMEM);
820 entry_info.hwi_num = num;
821 entry_info.hwi_max = max;
822 entry_info.hwi_prealloc = num_prealloc;
823 entry_info.hwi_rsrcpool = rsrc_pool;
824 entry_info.hwi_rsrcname = rsrc_name;
825 status = tavor_rsrc_hw_entries_init(state, &entry_info);
826 if (status != DDI_SUCCESS) {
827 tavor_rsrc_fini(state, cleanup);
828 /* Set "status" and "errormsg" and goto failure */
829 TAVOR_TNF_FAIL(DDI_FAILURE, "Extended QPC table");
830 goto rsrcinitp2_fail;
831 }
832 cleanup = TAVOR_RSRC_CLEANUP_LEVEL11;
833
834 /*
835 * Initialize the resource pool for the UD address vector table
836 * entries. Notice that the number of UDAVs is configurable. The
837 * configured value must be less that the maximum value (obtained
838 * from the QUERY_DEV_LIM command) or the initialization will fail.
839 */
840 num = ((uint64_t)1 << cfgprof->cp_log_num_ah);
841 max = ((uint64_t)1 << state->ts_devlim.log_max_av);
842 num_prealloc = 0;
843 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_UDAV];
844 rsrc_pool->rsrc_type = TAVOR_UDAV;
845 rsrc_pool->rsrc_loc = TAVOR_IN_DDR;
846 rsrc_pool->rsrc_pool_size = (TAVOR_UDAV_SIZE * num);
847 rsrc_pool->rsrc_shift = TAVOR_UDAV_SIZE_SHIFT;
848 rsrc_pool->rsrc_quantum = TAVOR_UDAV_SIZE;
849 rsrc_pool->rsrc_align = TAVOR_UDAV_SIZE;
850 rsrc_pool->rsrc_state = state;
851 rsrc_pool->rsrc_start = NULL;
852 TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_UDAV_VMEM);
853 entry_info.hwi_num = num;
854 entry_info.hwi_max = max;
855 entry_info.hwi_prealloc = num_prealloc;
856 entry_info.hwi_rsrcpool = rsrc_pool;
857 entry_info.hwi_rsrcname = rsrc_name;
858 status = tavor_rsrc_hw_entries_init(state, &entry_info);
859 if (status != DDI_SUCCESS) {
860 tavor_rsrc_fini(state, cleanup);
861 /* Set "status" and "errormsg" and goto failure */
862 TAVOR_TNF_FAIL(DDI_FAILURE, "UDAV table");
863 goto rsrcinitp2_fail;
864 }
865 cleanup = TAVOR_RSRC_CLEANUP_LEVEL12;
866
867 /*
868 * Initialize the resource pool for the UAR scratch table entries.
869 * Notice that the number of UARSCRs is configurable. The configured
870 * value must be less that the maximum value (obtained from the
871 * QUERY_DEV_LIM command) or the initialization will fail.
872 * Like the EQPCs above, UARSCR objects are not allocatable. The
873 * UARSCR table is also managed internally by the hardware and it
874 * is, therefore, unnecessary to initialize an additional vmem_arena
875 * for this type of object. We indicate this by setting the
876 * rsrc_quantum field to zero (indicating a zero-sized object).
877 */
878 uarscr_size = state->ts_devlim.uarscr_entry_sz;
879 num = ((uint64_t)1 << cfgprof->cp_log_num_uar);
880 max = ((uint64_t)1 << (state->ts_devlim.log_max_uar_sz + 20 -
881 PAGESHIFT));
882 num_prealloc = 0;
883 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_UAR_SCR];
884 rsrc_pool->rsrc_type = TAVOR_UAR_SCR;
885 rsrc_pool->rsrc_loc = TAVOR_IN_DDR;
886 rsrc_pool->rsrc_pool_size = (uarscr_size * num);
887 rsrc_pool->rsrc_shift = 0;
888 rsrc_pool->rsrc_quantum = 0;
889 rsrc_pool->rsrc_align = uarscr_size;
890 rsrc_pool->rsrc_state = state;
891 rsrc_pool->rsrc_start = NULL;
892 TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_UARSCR_VMEM);
893 entry_info.hwi_num = num;
894 entry_info.hwi_max = max;
895 entry_info.hwi_prealloc = num_prealloc;
896 entry_info.hwi_rsrcpool = rsrc_pool;
897 entry_info.hwi_rsrcname = rsrc_name;
898 status = tavor_rsrc_hw_entries_init(state, &entry_info);
899 if (status != DDI_SUCCESS) {
900 tavor_rsrc_fini(state, cleanup);
901 /* Set "status" and "errormsg" and goto failure */
902 TAVOR_TNF_FAIL(DDI_FAILURE, "UAR scratch table");
903 goto rsrcinitp2_fail;
904 }
905 cleanup = TAVOR_RSRC_CLEANUP_LEVEL13;
906
907 /*
908 * Initialize the resource pool for the SRQC table entries. Notice
909 * that the number of SRQs is configurable. The configured value must
910 * be less that the maximum value (obtained from the QUERY_DEV_LIM
911 * command) or the initialization will fail. Note also that a certain
912 * number of SRQ contexts must be set aside for Tavor firmware use.
913 *
914 * Note: We only allocate these resources if SRQ is enabled in the
915 * config profile; see below.
916 */
917 num = ((uint64_t)1 << cfgprof->cp_log_num_srq);
918 max = ((uint64_t)1 << state->ts_devlim.log_max_srq);
919 num_prealloc = ((uint64_t)1 << state->ts_devlim.log_rsvd_srq);
920
921 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_SRQC];
922 rsrc_pool->rsrc_type = TAVOR_SRQC;
923 rsrc_pool->rsrc_loc = TAVOR_IN_DDR;
924 rsrc_pool->rsrc_pool_size = (TAVOR_SRQC_SIZE * num);
925 rsrc_pool->rsrc_shift = TAVOR_SRQC_SIZE_SHIFT;
926 rsrc_pool->rsrc_quantum = TAVOR_SRQC_SIZE;
927 rsrc_pool->rsrc_align = (TAVOR_SRQC_SIZE * num);
928 rsrc_pool->rsrc_state = state;
929 rsrc_pool->rsrc_start = NULL;
930 TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_SRQC_VMEM);
931 entry_info.hwi_num = num;
932 entry_info.hwi_max = max;
933 entry_info.hwi_prealloc = num_prealloc;
934 entry_info.hwi_rsrcpool = rsrc_pool;
935 entry_info.hwi_rsrcname = rsrc_name;
936
937 /*
938 * SRQ support is configurable. Only if SRQ is enabled (the default)
939 * do we actually try to configure these resources. Otherwise, we
940 * simply set the cleanup level and continue on to the next resource
941 */
942 if (state->ts_cfg_profile->cp_srq_enable != 0) {
943 status = tavor_rsrc_hw_entries_init(state, &entry_info);
944 if (status != DDI_SUCCESS) {
945 tavor_rsrc_fini(state, cleanup);
946 /* Set "status" and "errormsg" and goto failure */
947 TAVOR_TNF_FAIL(DDI_FAILURE, "SRQC table");
948 goto rsrcinitp2_fail;
949 }
950 }
951 cleanup = TAVOR_RSRC_CLEANUP_LEVEL14;
952
953 /*
954 * Initialize the resource pool for "In" mailboxes. Notice that
955 * the number of "In" mailboxes, their size, and their location
956 * (DDR or system memory) is configurable. By default, however,
957 * all "In" mailboxes are located in system memory only (because
958 * they are primarily written to and rarely read from)
959 */
960 num = ((uint64_t)1 << cfgprof->cp_log_num_inmbox);
961 size = ((uint64_t)1 << cfgprof->cp_log_inmbox_size);
962 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_IN_MBOX];
963 rsrc_pool->rsrc_type = TAVOR_IN_MBOX;
964 rsrc_pool->rsrc_loc = TAVOR_IN_DDR;
965 rsrc_pool->rsrc_pool_size = (size * num);
966 rsrc_pool->rsrc_shift = cfgprof->cp_log_inmbox_size;
967 rsrc_pool->rsrc_quantum = size;
968 rsrc_pool->rsrc_align = TAVOR_MBOX_ALIGN;
969 rsrc_pool->rsrc_state = state;
970 TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_INMBOX_VMEM);
971 mbox_info.mbi_num = num;
972 mbox_info.mbi_size = size;
973 mbox_info.mbi_rsrcpool = rsrc_pool;
974 mbox_info.mbi_rsrcname = rsrc_name;
975 status = tavor_rsrc_mbox_init(state, &mbox_info);
976 if (status != DDI_SUCCESS) {
977 tavor_rsrc_fini(state, cleanup);
978 /* Set "status" and "errormsg" and goto failure */
979 TAVOR_TNF_FAIL(DDI_FAILURE, "in mailboxes");
980 goto rsrcinitp2_fail;
981 }
982 cleanup = TAVOR_RSRC_CLEANUP_LEVEL15;
983
984 /*
985 * Initialize the Tavor "In" mailbox list. This step actually uses
986 * the tavor_rsrc_alloc() for TAVOR_IN_MBOX to preallocate the
987 * "In" mailboxes, bind them for DMA access, and arrange them into
988 * an easily accessed fast-allocation mechanism (see tavor_cmd.c
989 * for more details)
990 */
991 status = tavor_inmbox_list_init(state);
992 if (status != DDI_SUCCESS) {
993 tavor_rsrc_fini(state, cleanup);
994 /* Set "status" and "errormsg" and goto failure */
995 TAVOR_TNF_FAIL(DDI_FAILURE, "in mailbox list");
996 goto rsrcinitp2_fail;
997 }
998 cleanup = TAVOR_RSRC_CLEANUP_LEVEL16;
999
1000 /*
1001 * Initialize the resource pool for interrupt "In" mailboxes. Notice
1002 * that the number of interrupt "In" mailboxes, their size, and their
1003 * location (DDR or system memory) is configurable. By default,
1004 * however, all interrupt "In" mailboxes are located in system memory
1005 * only (because they are primarily written to and rarely read from)
1006 */
1007 num = ((uint64_t)1 << cfgprof->cp_log_num_intr_inmbox);
1008 size = ((uint64_t)1 << cfgprof->cp_log_inmbox_size);
1009 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_INTR_IN_MBOX];
1010 rsrc_pool->rsrc_type = TAVOR_INTR_IN_MBOX;
1011 rsrc_pool->rsrc_loc = TAVOR_IN_DDR;
1012 rsrc_pool->rsrc_pool_size = (size * num);
1013 rsrc_pool->rsrc_shift = cfgprof->cp_log_inmbox_size;
1014 rsrc_pool->rsrc_quantum = size;
1015 rsrc_pool->rsrc_align = TAVOR_MBOX_ALIGN;
1016 rsrc_pool->rsrc_state = state;
1017 TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_INTR_INMBOX_VMEM);
1018 mbox_info.mbi_num = num;
1019 mbox_info.mbi_size = size;
1020 mbox_info.mbi_rsrcpool = rsrc_pool;
1021 mbox_info.mbi_rsrcname = rsrc_name;
1022 status = tavor_rsrc_mbox_init(state, &mbox_info);
1023 if (status != DDI_SUCCESS) {
1024 tavor_rsrc_fini(state, cleanup);
1025 /* Set "status" and "errormsg" and goto failure */
1026 TAVOR_TNF_FAIL(DDI_FAILURE, "in intr mailboxes");
1027 goto rsrcinitp2_fail;
1028 }
1029 cleanup = TAVOR_RSRC_CLEANUP_LEVEL17;
1030
1031 /*
1032 * Initialize the Tavor interrupt "In" mailbox list. This step
1033 * actually uses the tavor_rsrc_alloc() for TAVOR_IN_MBOX to
1034 * preallocate the interrupt "In" mailboxes, bind them for DMA access,
1035 * and arrange them into an easily accessed fast-allocation mechanism
1036 * (see tavor_cmd.c for more details)
1037 */
1038 status = tavor_intr_inmbox_list_init(state);
1039 if (status != DDI_SUCCESS) {
1040 tavor_rsrc_fini(state, cleanup);
1041 /* Set "status" and "errormsg" and goto failure */
1042 TAVOR_TNF_FAIL(DDI_FAILURE, "in intr mailbox list");
1043 goto rsrcinitp2_fail;
1044 }
1045 cleanup = TAVOR_RSRC_CLEANUP_LEVEL18;
1046
1047 /*
1048 * Initialize the Tavor command handling interfaces. This step
1049 * sets up the outstanding command tracking mechanism for easy access
1050 * and fast allocation (see tavor_cmd.c for more details).
1051 */
1052 status = tavor_outstanding_cmdlist_init(state);
1053 if (status != DDI_SUCCESS) {
1054 tavor_rsrc_fini(state, cleanup);
1055 /* Set "status" and "errormsg" and goto failure */
1056 TAVOR_TNF_FAIL(DDI_FAILURE, "outstanding cmd list");
1057 goto rsrcinitp2_fail;
1058 }
1059 cleanup = TAVOR_RSRC_CLEANUP_LEVEL19;
1060
1061 /*
1062 * Calculate (and validate) the size of Multicast Group (MCG) entries
1063 */
1064 status = tavor_rsrc_mcg_entry_get_size(state, &mcg_size_shift);
1065 if (status != DDI_SUCCESS) {
1066 tavor_rsrc_fini(state, cleanup);
1067 /* Set "status" and "errormsg" and goto failure */
1068 TAVOR_TNF_FAIL(DDI_FAILURE, "failed get MCG size");
1069 goto rsrcinitp2_fail;
1070 }
1071 mcg_size = TAVOR_MCGMEM_SZ(state);
1072
1073 /*
1074 * Initialize the resource pool for the MCG table entries. Notice
1075 * that the number of MCGs is configurable. The configured value must
1076 * be less that the maximum value (obtained from the QUERY_DEV_LIM
1077 * command) or the initialization will fail. Note also that a certain
1078 * number of MCGs must be set aside for Tavor firmware use (they
1079 * correspond to the number of MCGs used by the internal hash
1080 * function.
1081 */
1082 num = ((uint64_t)1 << cfgprof->cp_log_num_mcg);
1083 max = ((uint64_t)1 << state->ts_devlim.log_max_mcg);
1084 num_prealloc = ((uint64_t)1 << cfgprof->cp_log_num_mcg_hash);
1085 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_MCG];
1086 rsrc_pool->rsrc_type = TAVOR_MCG;
1087 rsrc_pool->rsrc_loc = TAVOR_IN_DDR;
1088 rsrc_pool->rsrc_pool_size = (mcg_size * num);
1089 rsrc_pool->rsrc_shift = mcg_size_shift;
1090 rsrc_pool->rsrc_quantum = mcg_size;
1091 rsrc_pool->rsrc_align = mcg_size;
1092 rsrc_pool->rsrc_state = state;
1093 rsrc_pool->rsrc_start = NULL;
1094 TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_MCG_VMEM);
1095 entry_info.hwi_num = num;
1096 entry_info.hwi_max = max;
1097 entry_info.hwi_prealloc = num_prealloc;
1098 entry_info.hwi_rsrcpool = rsrc_pool;
1099 entry_info.hwi_rsrcname = rsrc_name;
1100 status = tavor_rsrc_hw_entries_init(state, &entry_info);
1101 if (status != DDI_SUCCESS) {
1102 tavor_rsrc_fini(state, cleanup);
1103 /* Set "status" and "errormsg" and goto failure */
1104 TAVOR_TNF_FAIL(DDI_FAILURE, "MCG table");
1105 goto rsrcinitp2_fail;
1106 }
1107 cleanup = TAVOR_RSRC_CLEANUP_LEVEL20;
1108
1109 /*
1110 * Initialize the resource pool for the EQC table entries. Notice
1111 * that the number of EQs is hardcoded. The hardcoded value should
1112 * be less that the maximum value (obtained from the QUERY_DEV_LIM
1113 * command) or the initialization will fail.
1114 */
1115 num = TAVOR_NUM_EQ;
1116 max = ((uint64_t)1 << state->ts_devlim.log_max_eq);
1117 num_prealloc = 0;
1118 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_EQC];
1119 rsrc_pool->rsrc_type = TAVOR_EQC;
1120 rsrc_pool->rsrc_loc = TAVOR_IN_DDR;
1121 rsrc_pool->rsrc_pool_size = (TAVOR_EQC_SIZE * num);
1122 rsrc_pool->rsrc_shift = TAVOR_EQC_SIZE_SHIFT;
1123 rsrc_pool->rsrc_quantum = TAVOR_EQC_SIZE;
1124 rsrc_pool->rsrc_align = (TAVOR_EQC_SIZE * num);
1125 rsrc_pool->rsrc_state = state;
1126 rsrc_pool->rsrc_start = NULL;
1127 TAVOR_RSRC_NAME(rsrc_name, TAVOR_DDR_EQC_VMEM);
1128 entry_info.hwi_num = num;
1129 entry_info.hwi_max = max;
1130 entry_info.hwi_prealloc = num_prealloc;
1131 entry_info.hwi_rsrcpool = rsrc_pool;
1132 entry_info.hwi_rsrcname = rsrc_name;
1133 status = tavor_rsrc_hw_entries_init(state, &entry_info);
1134 if (status != DDI_SUCCESS) {
1135 tavor_rsrc_fini(state, cleanup);
1136 /* Set "status" and "errormsg" and goto failure */
1137 TAVOR_TNF_FAIL(DDI_FAILURE, "EQC table");
1138 goto rsrcinitp2_fail;
1139 }
1140 cleanup = TAVOR_RSRC_CLEANUP_LEVEL21;
1141
1142 /*
1143 * Initialize the resource pools for all objects that exist in
1144 * system memory. This includes PD handles, MR handle, EQ handles,
1145 * QP handles, etc. These objects are almost entirely managed using
1146 * kmem_cache routines. (See comment above for more detail)
1147 */
1148
1149 /*
1150 * Initialize the resource pool for the PD handles. Notice
1151 * that the number of PDHDLs is configurable. The configured value
1152 * must be less that the maximum value (obtained from the QUERY_DEV_LIM
1153 * command) or the initialization will fail. Note also that the PD
1154 * handle has constructor and destructor methods associated with it.
1155 */
1156 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_PDHDL];
1157 rsrc_pool->rsrc_type = TAVOR_PDHDL;
1158 rsrc_pool->rsrc_loc = TAVOR_IN_SYSMEM;
1159 rsrc_pool->rsrc_quantum = sizeof (struct tavor_sw_pd_s);
1160 rsrc_pool->rsrc_state = state;
1161 TAVOR_RSRC_NAME(rsrc_name, TAVOR_PDHDL_CACHE);
1162 hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_pd);
1163 hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_pd);
1164 hdl_info.swi_rsrcpool = rsrc_pool;
1165 hdl_info.swi_constructor = tavor_rsrc_pdhdl_constructor;
1166 hdl_info.swi_destructor = tavor_rsrc_pdhdl_destructor;
1167 hdl_info.swi_rsrcname = rsrc_name;
1168 hdl_info.swi_flags = TAVOR_SWHDL_KMEMCACHE_INIT;
1169 status = tavor_rsrc_pd_handles_init(state, &hdl_info);
1170 if (status != DDI_SUCCESS) {
1171 tavor_rsrc_fini(state, cleanup);
1172 /* Set "status" and "errormsg" and goto failure */
1173 TAVOR_TNF_FAIL(DDI_FAILURE, "PD handle");
1174 goto rsrcinitp2_fail;
1175 }
1176 cleanup = TAVOR_RSRC_CLEANUP_LEVEL22;
1177
1178 /*
1179 * Initialize the resource pool for the MR handles. Notice
1180 * that the number of MRHDLs is configurable. The configured value
1181 * must be less that the maximum value (obtained from the QUERY_DEV_LIM
1182 * command) or the initialization will fail.
1183 */
1184 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_MRHDL];
1185 rsrc_pool->rsrc_type = TAVOR_MRHDL;
1186 rsrc_pool->rsrc_loc = TAVOR_IN_SYSMEM;
1187 rsrc_pool->rsrc_quantum = sizeof (struct tavor_sw_mr_s);
1188 rsrc_pool->rsrc_state = state;
1189 TAVOR_RSRC_NAME(rsrc_name, TAVOR_MRHDL_CACHE);
1190 hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_mpt);
1191 hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_mpt);
1192 hdl_info.swi_rsrcpool = rsrc_pool;
1193 hdl_info.swi_constructor = tavor_rsrc_mrhdl_constructor;
1194 hdl_info.swi_destructor = tavor_rsrc_mrhdl_destructor;
1195 hdl_info.swi_rsrcname = rsrc_name;
1196 hdl_info.swi_flags = TAVOR_SWHDL_KMEMCACHE_INIT;
1197 status = tavor_rsrc_sw_handles_init(state, &hdl_info);
1198 if (status != DDI_SUCCESS) {
1199 tavor_rsrc_fini(state, cleanup);
1200 /* Set "status" and "errormsg" and goto failure */
1201 TAVOR_TNF_FAIL(DDI_FAILURE, "MR handle");
1202 goto rsrcinitp2_fail;
1203 }
1204 cleanup = TAVOR_RSRC_CLEANUP_LEVEL23;
1205
1206 /*
1207 * Initialize the resource pool for the EQ handles. Notice
1208 * that the number of EQHDLs is hardcoded. The hardcoded value
1209 * should be less that the maximum value (obtained from the
1210 * QUERY_DEV_LIM command) or the initialization will fail.
1211 */
1212 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_EQHDL];
1213 rsrc_pool->rsrc_type = TAVOR_EQHDL;
1214 rsrc_pool->rsrc_loc = TAVOR_IN_SYSMEM;
1215 rsrc_pool->rsrc_quantum = sizeof (struct tavor_sw_eq_s);
1216 rsrc_pool->rsrc_state = state;
1217 TAVOR_RSRC_NAME(rsrc_name, TAVOR_EQHDL_CACHE);
1218 hdl_info.swi_num = TAVOR_NUM_EQ;
1219 hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_eq);
1220 hdl_info.swi_rsrcpool = rsrc_pool;
1221 hdl_info.swi_constructor = NULL;
1222 hdl_info.swi_destructor = NULL;
1223 hdl_info.swi_rsrcname = rsrc_name;
1224 hdl_info.swi_flags = TAVOR_SWHDL_KMEMCACHE_INIT;
1225 status = tavor_rsrc_sw_handles_init(state, &hdl_info);
1226 if (status != DDI_SUCCESS) {
1227 tavor_rsrc_fini(state, cleanup);
1228 /* Set "status" and "errormsg" and goto failure */
1229 TAVOR_TNF_FAIL(DDI_FAILURE, "EQ handle");
1230 goto rsrcinitp2_fail;
1231 }
1232 cleanup = TAVOR_RSRC_CLEANUP_LEVEL24;
1233
1234 /*
1235 * Initialize the resource pool for the CQ handles. Notice
1236 * that the number of CQHDLs is configurable. The configured value
1237 * must be less that the maximum value (obtained from the QUERY_DEV_LIM
1238 * command) or the initialization will fail. Note also that the CQ
1239 * handle has constructor and destructor methods associated with it.
1240 */
1241 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_CQHDL];
1242 rsrc_pool->rsrc_type = TAVOR_CQHDL;
1243 rsrc_pool->rsrc_loc = TAVOR_IN_SYSMEM;
1244 rsrc_pool->rsrc_quantum = sizeof (struct tavor_sw_cq_s);
1245 rsrc_pool->rsrc_state = state;
1246 TAVOR_RSRC_NAME(rsrc_name, TAVOR_CQHDL_CACHE);
1247 hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_cq);
1248 hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_cq);
1249 hdl_info.swi_rsrcpool = rsrc_pool;
1250 hdl_info.swi_constructor = tavor_rsrc_cqhdl_constructor;
1251 hdl_info.swi_destructor = tavor_rsrc_cqhdl_destructor;
1252 hdl_info.swi_rsrcname = rsrc_name;
1253 hdl_info.swi_flags = (TAVOR_SWHDL_KMEMCACHE_INIT |
1254 TAVOR_SWHDL_TABLE_INIT);
1255 hdl_info.swi_prealloc_sz = sizeof (tavor_cqhdl_t);
1256 status = tavor_rsrc_sw_handles_init(state, &hdl_info);
1257 if (status != DDI_SUCCESS) {
1258 tavor_rsrc_fini(state, cleanup);
1259 /* Set "status" and "errormsg" and goto failure */
1260 TAVOR_TNF_FAIL(DDI_FAILURE, "CQ handle");
1261 goto rsrcinitp2_fail;
1262 }
1263
1264 /*
1265 * Save away the pointer to the central list of CQ handle pointers
1266 * This this is used as a mechanism to enable fast CQnumber-to-CQhandle
1267 * lookup during EQ event processing. The table is a list of
1268 * tavor_cqhdl_t allocated by the above routine because of the
1269 * TAVOR_SWHDL_TABLE_INIT flag. The table has as many tavor_cqhdl_t
1270 * as the number of CQs.
1271 */
1272 state->ts_cqhdl = hdl_info.swi_table_ptr;
1273 cleanup = TAVOR_RSRC_CLEANUP_LEVEL25;
1274
1275 /*
1276 * Initialize the resource pool for the SRQ handles. Notice
1277 * that the number of SRQHDLs is configurable. The configured value
1278 * must be less that the maximum value (obtained from the QUERY_DEV_LIM
1279 * command) or the initialization will fail. Note also that the SRQ
1280 * handle has constructor and destructor methods associated with it.
1281 *
1282 * Note: We only allocate these resources if SRQ is enabled in the
1283 * config profile; see below.
1284 */
1285 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_SRQHDL];
1286 rsrc_pool->rsrc_type = TAVOR_SRQHDL;
1287 rsrc_pool->rsrc_loc = TAVOR_IN_SYSMEM;
1288 rsrc_pool->rsrc_quantum = sizeof (struct tavor_sw_srq_s);
1289 rsrc_pool->rsrc_state = state;
1290 TAVOR_RSRC_NAME(rsrc_name, TAVOR_SRQHDL_CACHE);
1291 hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_srq);
1292 hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_srq);
1293 hdl_info.swi_rsrcpool = rsrc_pool;
1294 hdl_info.swi_constructor = tavor_rsrc_srqhdl_constructor;
1295 hdl_info.swi_destructor = tavor_rsrc_srqhdl_destructor;
1296 hdl_info.swi_rsrcname = rsrc_name;
1297 hdl_info.swi_flags = (TAVOR_SWHDL_KMEMCACHE_INIT |
1298 TAVOR_SWHDL_TABLE_INIT);
1299 hdl_info.swi_prealloc_sz = sizeof (tavor_srqhdl_t);
1300
1301 /*
1302 * SRQ support is configurable. Only if SRQ is enabled (the default)
1303 * do we actually try to configure these resources. Otherwise, we
1304 * simply set the cleanup level and continue on to the next resource
1305 */
1306 if (state->ts_cfg_profile->cp_srq_enable != 0) {
1307 status = tavor_rsrc_sw_handles_init(state, &hdl_info);
1308 if (status != DDI_SUCCESS) {
1309 tavor_rsrc_fini(state, cleanup);
1310 /* Set "status" and "errormsg" and goto failure */
1311 TAVOR_TNF_FAIL(DDI_FAILURE, "SRQ handle");
1312 goto rsrcinitp2_fail;
1313 }
1314
1315 /*
1316 * Save away the pointer to the central list of SRQ handle
1317 * pointers This this is used as a mechanism to enable fast
1318 * SRQnumber-to-SRQhandle lookup. The table is a list of
1319 * tavor_srqhdl_t allocated by the above routine because of the
1320 * TAVOR_SWHDL_TABLE_INIT flag. The table has as many
1321 * tavor_srqhdl_t as the number of SRQs.
1322 */
1323 state->ts_srqhdl = hdl_info.swi_table_ptr;
1324 }
1325 cleanup = TAVOR_RSRC_CLEANUP_LEVEL26;
1326
1327 /*
1328 * Initialize the resource pool for the address handles. Notice
1329 * that the number of AHHDLs is configurable. The configured value
1330 * must be less that the maximum value (obtained from the QUERY_DEV_LIM
1331 * command) or the initialization will fail.
1332 */
1333 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_AHHDL];
1334 rsrc_pool->rsrc_type = TAVOR_AHHDL;
1335 rsrc_pool->rsrc_loc = TAVOR_IN_SYSMEM;
1336 rsrc_pool->rsrc_quantum = sizeof (struct tavor_sw_ah_s);
1337 rsrc_pool->rsrc_state = state;
1338 TAVOR_RSRC_NAME(rsrc_name, TAVOR_AHHDL_CACHE);
1339 hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_ah);
1340 hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_av);
1341 hdl_info.swi_rsrcpool = rsrc_pool;
1342 hdl_info.swi_constructor = tavor_rsrc_ahhdl_constructor;
1343 hdl_info.swi_destructor = tavor_rsrc_ahhdl_destructor;
1344 hdl_info.swi_rsrcname = rsrc_name;
1345 hdl_info.swi_flags = TAVOR_SWHDL_KMEMCACHE_INIT;
1346 status = tavor_rsrc_sw_handles_init(state, &hdl_info);
1347 if (status != DDI_SUCCESS) {
1348 tavor_rsrc_fini(state, cleanup);
1349 /* Set "status" and "errormsg" and goto failure */
1350 TAVOR_TNF_FAIL(DDI_FAILURE, "AH handle");
1351 goto rsrcinitp2_fail;
1352 }
1353 cleanup = TAVOR_RSRC_CLEANUP_LEVEL27;
1354
1355 /*
1356 * Initialize the resource pool for the QP handles. Notice
1357 * that the number of QPHDLs is configurable. The configured value
1358 * must be less that the maximum value (obtained from the QUERY_DEV_LIM
1359 * command) or the initialization will fail. Note also that the QP
1360 * handle has constructor and destructor methods associated with it.
1361 */
1362 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_QPHDL];
1363 rsrc_pool->rsrc_type = TAVOR_QPHDL;
1364 rsrc_pool->rsrc_loc = TAVOR_IN_SYSMEM;
1365 rsrc_pool->rsrc_quantum = sizeof (struct tavor_sw_qp_s);
1366 rsrc_pool->rsrc_state = state;
1367 TAVOR_RSRC_NAME(rsrc_name, TAVOR_QPHDL_CACHE);
1368 hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_qp);
1369 hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_qp);
1370 hdl_info.swi_rsrcpool = rsrc_pool;
1371 hdl_info.swi_constructor = tavor_rsrc_qphdl_constructor;
1372 hdl_info.swi_destructor = tavor_rsrc_qphdl_destructor;
1373 hdl_info.swi_rsrcname = rsrc_name;
1374 hdl_info.swi_flags = (TAVOR_SWHDL_KMEMCACHE_INIT |
1375 TAVOR_SWHDL_TABLE_INIT);
1376 hdl_info.swi_prealloc_sz = sizeof (tavor_qphdl_t);
1377 status = tavor_rsrc_sw_handles_init(state, &hdl_info);
1378 if (status != DDI_SUCCESS) {
1379 tavor_rsrc_fini(state, cleanup);
1380 /* Set "status" and "errormsg" and goto failure */
1381 TAVOR_TNF_FAIL(DDI_FAILURE, "QP handle");
1382 goto rsrcinitp2_fail;
1383 }
1384
1385 /*
1386 * Save away the pointer to the central list of QP handle pointers
1387 * This this is used as a mechanism to enable fast QPnumber-to-QPhandle
1388 * lookup during CQ event processing. The table is a list of
1389 * tavor_qphdl_t allocated by the above routine because of the
1390 * TAVOR_SWHDL_TABLE_INIT flag. The table has as many tavor_qphdl_t
1391 * as the number of QPs.
1392 */
1393 state->ts_qphdl = hdl_info.swi_table_ptr;
1394 cleanup = TAVOR_RSRC_CLEANUP_LEVEL28;
1395
1396 /*
1397 * Initialize the resource pool for the reference count handles.
1398 * Notice that the number of REFCNTs is configurable, but it's value
1399 * is set to the number of MPTs. Since REFCNTs are used to support
1400 * shared memory regions, it is possible that we might require as
1401 * one REFCNT for every MPT.
1402 */
1403 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_REFCNT];
1404 rsrc_pool->rsrc_type = TAVOR_REFCNT;
1405 rsrc_pool->rsrc_loc = TAVOR_IN_SYSMEM;
1406 rsrc_pool->rsrc_quantum = sizeof (tavor_sw_refcnt_t);
1407 rsrc_pool->rsrc_state = state;
1408 TAVOR_RSRC_NAME(rsrc_name, TAVOR_REFCNT_CACHE);
1409 hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_mpt);
1410 hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_mpt);
1411 hdl_info.swi_rsrcpool = rsrc_pool;
1412 hdl_info.swi_constructor = tavor_rsrc_refcnt_constructor;
1413 hdl_info.swi_destructor = tavor_rsrc_refcnt_destructor;
1414 hdl_info.swi_rsrcname = rsrc_name;
1415 hdl_info.swi_flags = TAVOR_SWHDL_KMEMCACHE_INIT;
1416 status = tavor_rsrc_sw_handles_init(state, &hdl_info);
1417 if (status != DDI_SUCCESS) {
1418 tavor_rsrc_fini(state, cleanup);
1419 /* Set "status" and "errormsg" and goto failure */
1420 TAVOR_TNF_FAIL(DDI_FAILURE, "reference count handle");
1421 goto rsrcinitp2_fail;
1422 }
1423 cleanup = TAVOR_RSRC_CLEANUP_LEVEL29;
1424
1425 /*
1426 * Initialize the resource pool for the MCG handles. Notice that for
1427 * these MCG handles, we are allocating a table of structures (used to
1428 * keep track of the MCG entries that are being written to hardware
1429 * and to speed up multicast attach/detach operations).
1430 */
1431 hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_mcg);
1432 hdl_info.swi_max = ((uint64_t)1 << state->ts_devlim.log_max_mcg);
1433 hdl_info.swi_flags = TAVOR_SWHDL_TABLE_INIT;
1434 hdl_info.swi_prealloc_sz = sizeof (struct tavor_sw_mcg_list_s);
1435 status = tavor_rsrc_sw_handles_init(state, &hdl_info);
1436 if (status != DDI_SUCCESS) {
1437 tavor_rsrc_fini(state, cleanup);
1438 /* Set "status" and "errormsg" and goto failure */
1439 TAVOR_TNF_FAIL(DDI_FAILURE, "MCG handle");
1440 goto rsrcinitp2_fail;
1441 }
1442 state->ts_mcghdl = hdl_info.swi_table_ptr;
1443 cleanup = TAVOR_RSRC_CLEANUP_LEVEL30;
1444
1445 /*
1446 * Initialize the resource pools for all objects that exist in
1447 * UAR memory. The only objects that are allocated from UAR memory
1448 * are the UAR pages which are used for holding Tavor hardware's
1449 * doorbell registers.
1450 */
1451
1452 /*
1453 * Initialize the resource pool for the UAR pages. Notice
1454 * that the number of UARPGs is configurable. The configured value
1455 * must be less that the maximum value (obtained from the QUERY_DEV_LIM
1456 * command) or the initialization will fail. Note also that by
1457 * specifying the rsrc_start parameter in advance, we direct the
1458 * initialization routine not to attempt to allocated space from the
1459 * Tavor DDR vmem_arena.
1460 */
1461 num = ((uint64_t)1 << cfgprof->cp_log_num_uar);
1462 max = ((uint64_t)1 << (state->ts_devlim.log_max_uar_sz + 20 -
1463 PAGESHIFT));
1464 num_prealloc = 0;
1465 rsrc_pool = &state->ts_rsrc_hdl[TAVOR_UARPG];
1466 rsrc_pool->rsrc_type = TAVOR_UARPG;
1467 rsrc_pool->rsrc_loc = TAVOR_IN_UAR;
1468 rsrc_pool->rsrc_pool_size = (num << PAGESHIFT);
1469 rsrc_pool->rsrc_shift = PAGESHIFT;
1470 rsrc_pool->rsrc_quantum = PAGESIZE;
1471 rsrc_pool->rsrc_align = PAGESIZE;
1472 rsrc_pool->rsrc_state = state;
1473 rsrc_pool->rsrc_start = (void *)state->ts_reg_uar_baseaddr;
1474 TAVOR_RSRC_NAME(rsrc_name, TAVOR_UAR_VMEM);
1475 entry_info.hwi_num = num;
1476 entry_info.hwi_max = max;
1477 entry_info.hwi_prealloc = num_prealloc;
1478 entry_info.hwi_rsrcpool = rsrc_pool;
1479 entry_info.hwi_rsrcname = rsrc_name;
1480 status = tavor_rsrc_hw_entries_init(state, &entry_info);
1481 if (status != DDI_SUCCESS) {
1482 tavor_rsrc_fini(state, cleanup);
1483 /* Set "status" and "errormsg" and goto failure */
1484 TAVOR_TNF_FAIL(DDI_FAILURE, "UAR page table");
1485 goto rsrcinitp2_fail;
1486 }
1487 cleanup = TAVOR_RSRC_CLEANUP_ALL;
1488
1489 kmem_free(rsrc_name, TAVOR_RSRC_NAME_MAXLEN);
1490 TAVOR_TNF_EXIT(tavor_rsrc_init_phase2);
1491 return (DDI_SUCCESS);
1492
1493 rsrcinitp2_fail:
1494 kmem_free(rsrc_name, TAVOR_RSRC_NAME_MAXLEN);
1495 TNF_PROBE_1(tavor_rsrc_init_phase2_fail, TAVOR_TNF_ERROR, "",
1496 tnf_string, msg, errormsg);
1497 TAVOR_TNF_EXIT(tavor_rsrc_init_phase2);
1498 return (status);
1499 }
1500
1501
1502 /*
1503 * tavor_rsrc_fini()
1504 * Context: Only called from attach() and/or detach() path contexts
1505 */
1506 void
tavor_rsrc_fini(tavor_state_t * state,tavor_rsrc_cleanup_level_t clean)1507 tavor_rsrc_fini(tavor_state_t *state, tavor_rsrc_cleanup_level_t clean)
1508 {
1509 tavor_rsrc_sw_hdl_info_t hdl_info;
1510 tavor_rsrc_hw_entry_info_t entry_info;
1511 tavor_rsrc_mbox_info_t mbox_info;
1512 tavor_cfg_profile_t *cfgprof;
1513
1514 TAVOR_TNF_ENTER(tavor_rsrc_fini);
1515
1516 ASSERT(state != NULL);
1517
1518 cfgprof = state->ts_cfg_profile;
1519
1520 switch (clean) {
1521 /*
1522 * If we add more resources that need to be cleaned up here, we should
1523 * ensure that TAVOR_RSRC_CLEANUP_ALL is still the first entry (i.e.
1524 * corresponds to the last resource allocated).
1525 */
1526 case TAVOR_RSRC_CLEANUP_ALL:
1527 /* Cleanup the UAR page resource pool */
1528 entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_UARPG];
1529 tavor_rsrc_hw_entries_fini(state, &entry_info);
1530 /* FALLTHROUGH */
1531
1532 case TAVOR_RSRC_CLEANUP_LEVEL30:
1533 /* Cleanup the central MCG handle pointers list */
1534 hdl_info.swi_rsrcpool = NULL;
1535 hdl_info.swi_table_ptr = state->ts_mcghdl;
1536 hdl_info.swi_num =
1537 ((uint64_t)1 << cfgprof->cp_log_num_mcg);
1538 hdl_info.swi_prealloc_sz = sizeof (struct tavor_sw_mcg_list_s);
1539 tavor_rsrc_sw_handles_fini(state, &hdl_info);
1540 /* FALLTHROUGH */
1541
1542 case TAVOR_RSRC_CLEANUP_LEVEL29:
1543 /* Cleanup the reference count resource pool */
1544 hdl_info.swi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_REFCNT];
1545 hdl_info.swi_table_ptr = NULL;
1546 tavor_rsrc_sw_handles_fini(state, &hdl_info);
1547 /* FALLTHROUGH */
1548
1549 case TAVOR_RSRC_CLEANUP_LEVEL28:
1550 /* Cleanup the QP handle resource pool */
1551 hdl_info.swi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_QPHDL];
1552 hdl_info.swi_table_ptr = state->ts_qphdl;
1553 hdl_info.swi_num =
1554 ((uint64_t)1 << cfgprof->cp_log_num_qp);
1555 hdl_info.swi_prealloc_sz = sizeof (tavor_qphdl_t);
1556 tavor_rsrc_sw_handles_fini(state, &hdl_info);
1557 /* FALLTHROUGH */
1558
1559 case TAVOR_RSRC_CLEANUP_LEVEL27:
1560 /* Cleanup the address handle resource pool */
1561 hdl_info.swi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_AHHDL];
1562 hdl_info.swi_table_ptr = NULL;
1563 tavor_rsrc_sw_handles_fini(state, &hdl_info);
1564 /* FALLTHROUGH */
1565
1566 case TAVOR_RSRC_CLEANUP_LEVEL26:
1567 /*
1568 * Cleanup the SRQ handle resource pool.
1569 *
1570 * Note: We only clean up if SRQ is enabled. Otherwise we
1571 * simply fallthrough to the next resource cleanup.
1572 */
1573 if (state->ts_cfg_profile->cp_srq_enable != 0) {
1574 hdl_info.swi_rsrcpool =
1575 &state->ts_rsrc_hdl[TAVOR_SRQHDL];
1576 hdl_info.swi_table_ptr = state->ts_srqhdl;
1577 hdl_info.swi_num =
1578 ((uint64_t)1 << cfgprof->cp_log_num_srq);
1579 hdl_info.swi_prealloc_sz = sizeof (tavor_srqhdl_t);
1580 tavor_rsrc_sw_handles_fini(state, &hdl_info);
1581 }
1582 /* FALLTHROUGH */
1583
1584 case TAVOR_RSRC_CLEANUP_LEVEL25:
1585 /* Cleanup the CQ handle resource pool */
1586 hdl_info.swi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_CQHDL];
1587 hdl_info.swi_table_ptr = state->ts_cqhdl;
1588 hdl_info.swi_num =
1589 ((uint64_t)1 << cfgprof->cp_log_num_cq);
1590 hdl_info.swi_prealloc_sz = sizeof (tavor_cqhdl_t);
1591 tavor_rsrc_sw_handles_fini(state, &hdl_info);
1592 /* FALLTHROUGH */
1593
1594 case TAVOR_RSRC_CLEANUP_LEVEL24:
1595 /* Cleanup the EQ handle resource pool */
1596 hdl_info.swi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_EQHDL];
1597 hdl_info.swi_table_ptr = NULL;
1598 tavor_rsrc_sw_handles_fini(state, &hdl_info);
1599 /* FALLTHROUGH */
1600
1601 case TAVOR_RSRC_CLEANUP_LEVEL23:
1602 /* Cleanup the MR handle resource pool */
1603 hdl_info.swi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_MRHDL];
1604 hdl_info.swi_table_ptr = NULL;
1605 tavor_rsrc_sw_handles_fini(state, &hdl_info);
1606 /* FALLTHROUGH */
1607
1608 case TAVOR_RSRC_CLEANUP_LEVEL22:
1609 /* Cleanup the PD handle resource pool */
1610 hdl_info.swi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_PDHDL];
1611 hdl_info.swi_table_ptr = NULL;
1612 tavor_rsrc_pd_handles_fini(state, &hdl_info);
1613 /* FALLTHROUGH */
1614
1615 case TAVOR_RSRC_CLEANUP_LEVEL21:
1616 /* Cleanup the EQC table resource pool */
1617 entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_EQC];
1618 tavor_rsrc_hw_entries_fini(state, &entry_info);
1619 /* FALLTHROUGH */
1620
1621 case TAVOR_RSRC_CLEANUP_LEVEL20:
1622 /* Cleanup the MCG table resource pool */
1623 entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_MCG];
1624 tavor_rsrc_hw_entries_fini(state, &entry_info);
1625 /* FALLTHROUGH */
1626
1627 case TAVOR_RSRC_CLEANUP_LEVEL19:
1628 /* Cleanup the outstanding command list */
1629 tavor_outstanding_cmdlist_fini(state);
1630 /* FALLTHROUGH */
1631
1632 case TAVOR_RSRC_CLEANUP_LEVEL18:
1633 /* Cleanup the "In" mailbox list */
1634 tavor_intr_inmbox_list_fini(state);
1635 /* FALLTHROUGH */
1636
1637 case TAVOR_RSRC_CLEANUP_LEVEL17:
1638 /* Cleanup the interrupt "In" mailbox resource pool */
1639 mbox_info.mbi_rsrcpool = &state->ts_rsrc_hdl[
1640 TAVOR_INTR_IN_MBOX];
1641 tavor_rsrc_mbox_fini(state, &mbox_info);
1642 /* FALLTHROUGH */
1643
1644 case TAVOR_RSRC_CLEANUP_LEVEL16:
1645 /* Cleanup the "In" mailbox list */
1646 tavor_inmbox_list_fini(state);
1647 /* FALLTHROUGH */
1648
1649 case TAVOR_RSRC_CLEANUP_LEVEL15:
1650 /* Cleanup the "In" mailbox resource pool */
1651 mbox_info.mbi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_IN_MBOX];
1652 tavor_rsrc_mbox_fini(state, &mbox_info);
1653 /* FALLTHROUGH */
1654
1655 case TAVOR_RSRC_CLEANUP_LEVEL14:
1656 /*
1657 * Cleanup the SRQC table resource pool.
1658 *
1659 * Note: We only clean up if SRQ is enabled. Otherwise we
1660 * simply fallthrough to the next resource cleanup.
1661 */
1662 if (state->ts_cfg_profile->cp_srq_enable != 0) {
1663 entry_info.hwi_rsrcpool =
1664 &state->ts_rsrc_hdl[TAVOR_SRQC];
1665 tavor_rsrc_hw_entries_fini(state, &entry_info);
1666 }
1667 /* FALLTHROUGH */
1668
1669 case TAVOR_RSRC_CLEANUP_LEVEL13:
1670 /* Cleanup the UAR scratch table resource pool */
1671 entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_UAR_SCR];
1672 tavor_rsrc_hw_entries_fini(state, &entry_info);
1673 /* FALLTHROUGH */
1674
1675 case TAVOR_RSRC_CLEANUP_LEVEL12:
1676 /* Cleanup the UDAV table resource pool */
1677 entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_UDAV];
1678 tavor_rsrc_hw_entries_fini(state, &entry_info);
1679 /* FALLTHROUGH */
1680
1681 case TAVOR_RSRC_CLEANUP_LEVEL11:
1682 /* Cleanup the EQPC table resource pool */
1683 entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_EQPC];
1684 tavor_rsrc_hw_entries_fini(state, &entry_info);
1685 /* FALLTHROUGH */
1686
1687 case TAVOR_RSRC_CLEANUP_LEVEL10:
1688 /* Cleanup the CQC table resource pool */
1689 entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_CQC];
1690 tavor_rsrc_hw_entries_fini(state, &entry_info);
1691 /* FALLTHROUGH */
1692
1693 case TAVOR_RSRC_CLEANUP_LEVEL9:
1694 /* Cleanup the RDB table resource pool */
1695 entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_RDB];
1696 tavor_rsrc_hw_entries_fini(state, &entry_info);
1697 /* FALLTHROUGH */
1698
1699 case TAVOR_RSRC_CLEANUP_LEVEL8:
1700 /* Cleanup the QPC table resource pool */
1701 entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_QPC];
1702 tavor_rsrc_hw_entries_fini(state, &entry_info);
1703 /* FALLTHROUGH */
1704
1705 case TAVOR_RSRC_CLEANUP_LEVEL7:
1706 /* Cleanup the MTT table resource pool */
1707 entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_MTT];
1708 tavor_rsrc_hw_entries_fini(state, &entry_info);
1709 /* FALLTHROUGH */
1710
1711 case TAVOR_RSRC_CLEANUP_LEVEL6:
1712 /* Cleanup the MPT table resource pool */
1713 entry_info.hwi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_MPT];
1714 tavor_rsrc_hw_entries_fini(state, &entry_info);
1715 /* FALLTHROUGH */
1716
1717 case TAVOR_RSRC_CLEANUP_LEVEL5:
1718 /* Destroy the vmem arena for DDR memory */
1719 vmem_destroy(state->ts_ddrvmem);
1720 break;
1721
1722 /*
1723 * The cleanup below comes from the "Phase 1" initialization step.
1724 * (see tavor_rsrc_init_phase1() above)
1725 */
1726 case TAVOR_RSRC_CLEANUP_PHASE1_COMPLETE:
1727 /* Cleanup the interrupt "Out" mailbox list */
1728 tavor_intr_outmbox_list_fini(state);
1729 /* FALLTHROUGH */
1730
1731 case TAVOR_RSRC_CLEANUP_LEVEL3:
1732 /* Cleanup the "Out" mailbox resource pool */
1733 mbox_info.mbi_rsrcpool = &state->ts_rsrc_hdl[
1734 TAVOR_INTR_OUT_MBOX];
1735 tavor_rsrc_mbox_fini(state, &mbox_info);
1736 /* FALLTHROUGH */
1737
1738 case TAVOR_RSRC_CLEANUP_LEVEL2:
1739 /* Cleanup the "Out" mailbox list */
1740 tavor_outmbox_list_fini(state);
1741 /* FALLTHROUGH */
1742
1743 case TAVOR_RSRC_CLEANUP_LEVEL1:
1744 /* Cleanup the "Out" mailbox resource pool */
1745 mbox_info.mbi_rsrcpool = &state->ts_rsrc_hdl[TAVOR_OUT_MBOX];
1746 tavor_rsrc_mbox_fini(state, &mbox_info);
1747 /* FALLTHROUGH */
1748
1749 case TAVOR_RSRC_CLEANUP_LEVEL0:
1750 /* Free the array of tavor_rsrc_pool_info_t's */
1751 kmem_free(state->ts_rsrc_hdl, TAVOR_NUM_RESOURCES *
1752 sizeof (tavor_rsrc_pool_info_t));
1753 kmem_cache_destroy(state->ts_rsrc_cache);
1754 break;
1755
1756 default:
1757 TAVOR_WARNING(state, "unexpected resource cleanup level");
1758 TNF_PROBE_0(tavor_rsrc_fini_default_fail, TAVOR_TNF_ERROR, "");
1759 TAVOR_TNF_EXIT(tavor_rsrc_fini);
1760 return;
1761 }
1762
1763 TAVOR_TNF_EXIT(tavor_rsrc_fini);
1764 }
1765
1766
1767 /*
1768 * tavor_rsrc_mbox_init()
1769 * Context: Only called from attach() path context
1770 */
1771 static int
tavor_rsrc_mbox_init(tavor_state_t * state,tavor_rsrc_mbox_info_t * info)1772 tavor_rsrc_mbox_init(tavor_state_t *state, tavor_rsrc_mbox_info_t *info)
1773 {
1774 tavor_rsrc_pool_info_t *rsrc_pool;
1775 tavor_rsrc_priv_mbox_t *priv;
1776 vmem_t *vmp;
1777 uint64_t offset;
1778 uint_t dma_xfer_mode;
1779
1780 TAVOR_TNF_ENTER(tavor_rsrc_mbox_init);
1781
1782 ASSERT(state != NULL);
1783 ASSERT(info != NULL);
1784
1785 rsrc_pool = info->mbi_rsrcpool;
1786 ASSERT(rsrc_pool != NULL);
1787
1788 dma_xfer_mode = state->ts_cfg_profile->cp_streaming_consistent;
1789
1790 /* Allocate and initialize mailbox private structure */
1791 priv = kmem_zalloc(sizeof (tavor_rsrc_priv_mbox_t), KM_SLEEP);
1792 priv->pmb_dip = state->ts_dip;
1793 priv->pmb_acchdl = state->ts_reg_ddrhdl;
1794 priv->pmb_devaccattr = state->ts_reg_accattr;
1795 priv->pmb_xfer_mode = dma_xfer_mode;
1796
1797 /*
1798 * Initialize many of the default DMA attributes. Then set alignment
1799 * and scatter-gather restrictions specific for mailbox memory.
1800 */
1801 tavor_dma_attr_init(&priv->pmb_dmaattr);
1802 priv->pmb_dmaattr.dma_attr_align = TAVOR_MBOX_ALIGN;
1803 priv->pmb_dmaattr.dma_attr_sgllen = 1;
1804
1805 rsrc_pool->rsrc_private = priv;
1806
1807 /* Is object in DDR memory or system memory? */
1808 if (rsrc_pool->rsrc_loc == TAVOR_IN_DDR) {
1809 rsrc_pool->rsrc_ddr_offset = vmem_xalloc(state->ts_ddrvmem,
1810 rsrc_pool->rsrc_pool_size, rsrc_pool->rsrc_align,
1811 0, 0, NULL, NULL, VM_SLEEP);
1812 if (rsrc_pool->rsrc_ddr_offset == NULL) {
1813 /* Unable to alloc space for mailboxes */
1814 kmem_free(priv, sizeof (tavor_rsrc_priv_mbox_t));
1815 TNF_PROBE_0(tavor_rsrc_mbox_init_vma_fail,
1816 TAVOR_TNF_ERROR, "");
1817 TAVOR_TNF_EXIT(tavor_rsrc_mbox_init);
1818 return (DDI_FAILURE);
1819 }
1820
1821 /* Calculate offset and starting point (in DDR) */
1822 offset = ((uintptr_t)rsrc_pool->rsrc_ddr_offset -
1823 state->ts_ddr.ddr_baseaddr);
1824 rsrc_pool->rsrc_start =
1825 (void *)(uintptr_t)((uintptr_t)state->ts_reg_ddr_baseaddr +
1826 offset);
1827
1828 /* Create new vmem arena for the mailboxes */
1829 vmp = vmem_create(info->mbi_rsrcname,
1830 rsrc_pool->rsrc_ddr_offset, rsrc_pool->rsrc_pool_size,
1831 rsrc_pool->rsrc_quantum, NULL, NULL, NULL, 0, VM_SLEEP);
1832 if (vmp == NULL) {
1833 /* Unable to create vmem arena */
1834 vmem_xfree(state->ts_ddrvmem,
1835 rsrc_pool->rsrc_ddr_offset,
1836 rsrc_pool->rsrc_pool_size);
1837 kmem_free(priv, sizeof (tavor_rsrc_priv_mbox_t));
1838 TNF_PROBE_0(tavor_rsrc_mbox_init_vmem_create_fail,
1839 TAVOR_TNF_ERROR, "");
1840 TAVOR_TNF_EXIT(tavor_rsrc_mbox_init);
1841 return (DDI_FAILURE);
1842 }
1843 rsrc_pool->rsrc_vmp = vmp;
1844 } else {
1845 rsrc_pool->rsrc_ddr_offset = NULL;
1846 rsrc_pool->rsrc_start = NULL;
1847 rsrc_pool->rsrc_vmp = NULL;
1848 }
1849
1850 TAVOR_TNF_EXIT(tavor_rsrc_mbox_init);
1851 return (DDI_SUCCESS);
1852 }
1853
1854
1855 /*
1856 * tavor_rsrc_mbox_fini()
1857 * Context: Only called from attach() and/or detach() path contexts
1858 */
1859 static void
tavor_rsrc_mbox_fini(tavor_state_t * state,tavor_rsrc_mbox_info_t * info)1860 tavor_rsrc_mbox_fini(tavor_state_t *state, tavor_rsrc_mbox_info_t *info)
1861 {
1862 tavor_rsrc_pool_info_t *rsrc_pool;
1863
1864 TAVOR_TNF_ENTER(tavor_rsrc_mbox_fini);
1865
1866 ASSERT(state != NULL);
1867 ASSERT(info != NULL);
1868
1869 rsrc_pool = info->mbi_rsrcpool;
1870 ASSERT(rsrc_pool != NULL);
1871
1872 /* If mailboxes are DDR memory, then destroy and free up vmem */
1873 if (rsrc_pool->rsrc_loc == TAVOR_IN_DDR) {
1874
1875 /* Destroy the specially created mbox vmem arena */
1876 vmem_destroy(rsrc_pool->rsrc_vmp);
1877
1878 /* Free up the region from the ddr_vmem arena */
1879 vmem_xfree(state->ts_ddrvmem, rsrc_pool->rsrc_ddr_offset,
1880 rsrc_pool->rsrc_pool_size);
1881 }
1882
1883 /* Free up the private struct */
1884 kmem_free(rsrc_pool->rsrc_private, sizeof (tavor_rsrc_priv_mbox_t));
1885
1886 TAVOR_TNF_EXIT(tavor_rsrc_mbox_fini);
1887 }
1888
1889
1890 /*
1891 * tavor_rsrc_hw_entries_init()
1892 * Context: Only called from attach() path context
1893 */
1894 static int
tavor_rsrc_hw_entries_init(tavor_state_t * state,tavor_rsrc_hw_entry_info_t * info)1895 tavor_rsrc_hw_entries_init(tavor_state_t *state,
1896 tavor_rsrc_hw_entry_info_t *info)
1897 {
1898 tavor_rsrc_pool_info_t *rsrc_pool;
1899 tavor_rsrc_t *rsvd_rsrc = NULL;
1900 vmem_t *vmp;
1901 uint64_t num_hwentry, max_hwentry, num_prealloc;
1902 uint64_t offset;
1903 int status;
1904
1905 TAVOR_TNF_ENTER(tavor_rsrc_hw_entries_init);
1906
1907 ASSERT(state != NULL);
1908 ASSERT(info != NULL);
1909
1910 rsrc_pool = info->hwi_rsrcpool;
1911 ASSERT(rsrc_pool != NULL);
1912 num_hwentry = info->hwi_num;
1913 max_hwentry = info->hwi_max;
1914 num_prealloc = info->hwi_prealloc;
1915
1916 /* Make sure number of HW entries makes sense */
1917 if (num_hwentry > max_hwentry) {
1918 TNF_PROBE_2(tavor_rsrc_hw_entries_init_toomany_fail,
1919 TAVOR_TNF_ERROR, "", tnf_string, errmsg, "number of HW "
1920 "entries exceeds device maximum", tnf_uint, maxhw,
1921 max_hwentry);
1922 TAVOR_TNF_EXIT(tavor_rsrc_hw_entries_init);
1923 return (DDI_FAILURE);
1924 }
1925
1926 /*
1927 * Determine if we need to allocate DDR space to set up the
1928 * "rsrc_start" pointer. Not necessary if "rsrc_start" has already
1929 * been initialized (as is the case for the UAR page init).
1930 */
1931 if (rsrc_pool->rsrc_start == NULL) {
1932 /* Make sure HW entries table is aligned as specified */
1933 rsrc_pool->rsrc_ddr_offset = vmem_xalloc(state->ts_ddrvmem,
1934 rsrc_pool->rsrc_pool_size, rsrc_pool->rsrc_align,
1935 0, 0, NULL, NULL, VM_NOSLEEP | VM_FIRSTFIT);
1936 if (rsrc_pool->rsrc_ddr_offset == NULL) {
1937 /* Unable to alloc space for aligned HW table */
1938 TNF_PROBE_0(tavor_rsrc_hw_entry_table_vmxalloc_fail,
1939 TAVOR_TNF_ERROR, "");
1940 TAVOR_TNF_EXIT(tavor_rsrc_hw_entries_init);
1941 return (DDI_FAILURE);
1942 }
1943
1944 /* Calculate offset and starting point (in DDR) */
1945 offset = ((uintptr_t)rsrc_pool->rsrc_ddr_offset -
1946 state->ts_ddr.ddr_baseaddr);
1947 rsrc_pool->rsrc_start =
1948 (void *)(uintptr_t)((uintptr_t)state->ts_reg_ddr_baseaddr +
1949 offset);
1950 } else {
1951 rsrc_pool->rsrc_ddr_offset = rsrc_pool->rsrc_start;
1952 }
1953
1954 /*
1955 * Create new vmem arena for the HW entries table (if rsrc_quantum
1956 * is non-zero). Otherwise if rsrc_quantum is zero, then these HW
1957 * entries are not going to be dynamically allocatable (i.e. they
1958 * won't be allocated/freed through tavor_rsrc_alloc/free). This
1959 * latter option is used for EQPC and UARSCR resource which are, in
1960 * fact, managed by the Tavor hardware.
1961 */
1962 if (rsrc_pool->rsrc_quantum != 0) {
1963 vmp = vmem_create(info->hwi_rsrcname,
1964 rsrc_pool->rsrc_ddr_offset, rsrc_pool->rsrc_pool_size,
1965 rsrc_pool->rsrc_quantum, NULL, NULL, NULL, 0, VM_SLEEP);
1966 if (vmp == NULL) {
1967 /* Unable to create vmem arena */
1968 if (rsrc_pool->rsrc_ddr_offset !=
1969 rsrc_pool->rsrc_start) {
1970 vmem_xfree(state->ts_ddrvmem,
1971 rsrc_pool->rsrc_ddr_offset,
1972 rsrc_pool->rsrc_pool_size);
1973 }
1974 TNF_PROBE_0(tavor_rsrc_hw_entries_init_vmemcreate_fail,
1975 TAVOR_TNF_ERROR, "");
1976 TAVOR_TNF_EXIT(tavor_rsrc_hw_entries_init);
1977 return (DDI_FAILURE);
1978 }
1979 rsrc_pool->rsrc_vmp = vmp;
1980 } else {
1981 rsrc_pool->rsrc_vmp = NULL;
1982 }
1983
1984 /* The first HW entries may be reserved by Tavor firmware */
1985 if (num_prealloc != 0) {
1986 status = tavor_rsrc_alloc(state, rsrc_pool->rsrc_type,
1987 num_prealloc, TAVOR_SLEEP, &rsvd_rsrc);
1988 if (status != DDI_SUCCESS) {
1989 /* Unable to preallocate the reserved HW entries */
1990 if (rsrc_pool->rsrc_vmp != NULL) {
1991 vmem_destroy(rsrc_pool->rsrc_vmp);
1992 }
1993 if (rsrc_pool->rsrc_ddr_offset !=
1994 rsrc_pool->rsrc_start) {
1995 vmem_xfree(state->ts_ddrvmem,
1996 rsrc_pool->rsrc_ddr_offset,
1997 rsrc_pool->rsrc_pool_size);
1998 }
1999 TNF_PROBE_0(tavor_rsrc_hw_entries_init_pre_fail,
2000 TAVOR_TNF_ERROR, "");
2001 TAVOR_TNF_EXIT(tavor_rsrc_hw_entries_init);
2002 return (DDI_FAILURE);
2003 }
2004 }
2005 rsrc_pool->rsrc_private = rsvd_rsrc;
2006
2007 TAVOR_TNF_EXIT(tavor_rsrc_hw_entries_init);
2008 return (DDI_SUCCESS);
2009 }
2010
2011
2012 /*
2013 * tavor_rsrc_hw_entries_fini()
2014 * Context: Only called from attach() and/or detach() path contexts
2015 */
2016 static void
tavor_rsrc_hw_entries_fini(tavor_state_t * state,tavor_rsrc_hw_entry_info_t * info)2017 tavor_rsrc_hw_entries_fini(tavor_state_t *state,
2018 tavor_rsrc_hw_entry_info_t *info)
2019 {
2020 tavor_rsrc_pool_info_t *rsrc_pool;
2021 tavor_rsrc_t *rsvd_rsrc;
2022
2023 TAVOR_TNF_ENTER(tavor_rsrc_hw_entries_fini);
2024
2025 ASSERT(state != NULL);
2026 ASSERT(info != NULL);
2027
2028 rsrc_pool = info->hwi_rsrcpool;
2029 ASSERT(rsrc_pool != NULL);
2030
2031 /* Free up any "reserved" (i.e. preallocated) HW entries */
2032 rsvd_rsrc = (tavor_rsrc_t *)rsrc_pool->rsrc_private;
2033 if (rsvd_rsrc != NULL) {
2034 tavor_rsrc_free(state, &rsvd_rsrc);
2035 }
2036
2037 /*
2038 * If we've actually setup a vmem arena for the HW entries, then
2039 * destroy it now
2040 */
2041 if (rsrc_pool->rsrc_vmp != NULL) {
2042 vmem_destroy(rsrc_pool->rsrc_vmp);
2043 }
2044
2045 /*
2046 * Determine if a region was allocated from the tavor_ddr_vmem
2047 * arena (and free it up if necessary)
2048 */
2049 if (rsrc_pool->rsrc_ddr_offset != rsrc_pool->rsrc_start) {
2050 vmem_xfree(state->ts_ddrvmem, rsrc_pool->rsrc_ddr_offset,
2051 rsrc_pool->rsrc_pool_size);
2052 }
2053
2054 TAVOR_TNF_EXIT(tavor_rsrc_hw_entries_fini);
2055 }
2056
2057
2058 /*
2059 * tavor_rsrc_sw_handles_init()
2060 * Context: Only called from attach() path context
2061 */
2062 /* ARGSUSED */
2063 static int
tavor_rsrc_sw_handles_init(tavor_state_t * state,tavor_rsrc_sw_hdl_info_t * info)2064 tavor_rsrc_sw_handles_init(tavor_state_t *state, tavor_rsrc_sw_hdl_info_t *info)
2065 {
2066 tavor_rsrc_pool_info_t *rsrc_pool;
2067 uint64_t num_swhdl, max_swhdl, prealloc_sz;
2068
2069 TAVOR_TNF_ENTER(tavor_rsrc_sw_handles_init);
2070
2071 ASSERT(state != NULL);
2072 ASSERT(info != NULL);
2073
2074 rsrc_pool = info->swi_rsrcpool;
2075 ASSERT(rsrc_pool != NULL);
2076 num_swhdl = info->swi_num;
2077 max_swhdl = info->swi_max;
2078 prealloc_sz = info->swi_prealloc_sz;
2079
2080 /* Make sure number of SW handles makes sense */
2081 if (num_swhdl > max_swhdl) {
2082 TNF_PROBE_2(tavor_rsrc_sw_handles_init_toomany_fail,
2083 TAVOR_TNF_ERROR, "", tnf_string, errmsg, "number of SW "
2084 "handles exceeds maximum", tnf_uint, maxsw, max_swhdl);
2085 TAVOR_TNF_EXIT(tavor_rsrc_sw_handles_init);
2086 return (DDI_FAILURE);
2087 }
2088
2089 /*
2090 * Depending on the flags parameter, create a kmem_cache for some
2091 * number of software handle structures. Note: kmem_cache_create()
2092 * will SLEEP until successful.
2093 */
2094 if (info->swi_flags & TAVOR_SWHDL_KMEMCACHE_INIT) {
2095 rsrc_pool->rsrc_private = kmem_cache_create(
2096 info->swi_rsrcname, rsrc_pool->rsrc_quantum, 0,
2097 info->swi_constructor, info->swi_destructor, NULL,
2098 rsrc_pool->rsrc_state, NULL, 0);
2099 }
2100
2101 /* Allocate the central list of SW handle pointers */
2102 if (info->swi_flags & TAVOR_SWHDL_TABLE_INIT) {
2103 info->swi_table_ptr = kmem_zalloc(num_swhdl * prealloc_sz,
2104 KM_SLEEP);
2105 }
2106
2107 TAVOR_TNF_EXIT(tavor_rsrc_sw_handles_init);
2108 return (DDI_SUCCESS);
2109 }
2110
2111
2112 /*
2113 * tavor_rsrc_sw_handles_fini()
2114 * Context: Only called from attach() and/or detach() path contexts
2115 */
2116 /* ARGSUSED */
2117 static void
tavor_rsrc_sw_handles_fini(tavor_state_t * state,tavor_rsrc_sw_hdl_info_t * info)2118 tavor_rsrc_sw_handles_fini(tavor_state_t *state, tavor_rsrc_sw_hdl_info_t *info)
2119 {
2120 tavor_rsrc_pool_info_t *rsrc_pool;
2121 uint64_t num_swhdl, prealloc_sz;
2122
2123 TAVOR_TNF_ENTER(tavor_rsrc_sw_handles_fini);
2124
2125 ASSERT(state != NULL);
2126 ASSERT(info != NULL);
2127
2128 rsrc_pool = info->swi_rsrcpool;
2129 num_swhdl = info->swi_num;
2130 prealloc_sz = info->swi_prealloc_sz;
2131
2132 /*
2133 * If a "software handle" kmem_cache exists for this resource, then
2134 * destroy it now
2135 */
2136 if (rsrc_pool != NULL) {
2137 kmem_cache_destroy(rsrc_pool->rsrc_private);
2138 }
2139
2140 /* Free up this central list of SW handle pointers */
2141 if (info->swi_table_ptr != NULL) {
2142 kmem_free(info->swi_table_ptr, num_swhdl * prealloc_sz);
2143 }
2144
2145 TAVOR_TNF_EXIT(tavor_rsrc_sw_handles_fini);
2146 }
2147
2148
2149 /*
2150 * tavor_rsrc_pd_handles_init()
2151 * Context: Only called from attach() path context
2152 */
2153 static int
tavor_rsrc_pd_handles_init(tavor_state_t * state,tavor_rsrc_sw_hdl_info_t * info)2154 tavor_rsrc_pd_handles_init(tavor_state_t *state, tavor_rsrc_sw_hdl_info_t *info)
2155 {
2156 tavor_rsrc_pool_info_t *rsrc_pool;
2157 vmem_t *vmp;
2158 char vmem_name[TAVOR_RSRC_NAME_MAXLEN];
2159 int status;
2160
2161 TAVOR_TNF_ENTER(tavor_rsrc_pd_handles_init);
2162
2163 ASSERT(state != NULL);
2164 ASSERT(info != NULL);
2165
2166 rsrc_pool = info->swi_rsrcpool;
2167 ASSERT(rsrc_pool != NULL);
2168
2169 /* Initialize the resource pool for software handle table */
2170 status = tavor_rsrc_sw_handles_init(state, info);
2171 if (status != DDI_SUCCESS) {
2172 TNF_PROBE_0(tavor_rsrc_pdhdl_alloc_fail, TAVOR_TNF_ERROR, "");
2173 TAVOR_TNF_EXIT(tavor_rsrc_pdhdl_alloc);
2174 return (DDI_FAILURE);
2175 }
2176
2177 /* Build vmem arena name from Tavor instance */
2178 TAVOR_RSRC_NAME(vmem_name, TAVOR_PDHDL_VMEM);
2179
2180 /* Create new vmem arena for PD numbers */
2181 vmp = vmem_create(vmem_name, (caddr_t)1, info->swi_num, 1, NULL,
2182 NULL, NULL, 0, VM_SLEEP | VMC_IDENTIFIER);
2183 if (vmp == NULL) {
2184 /* Unable to create vmem arena */
2185 info->swi_table_ptr = NULL;
2186 tavor_rsrc_sw_handles_fini(state, info);
2187 TNF_PROBE_0(tavor_rsrc_pd_handles_init_vmem_create_fail,
2188 TAVOR_TNF_ERROR, "");
2189 TAVOR_TNF_EXIT(tavor_rsrc_pd_handles_init);
2190 return (DDI_FAILURE);
2191 }
2192 rsrc_pool->rsrc_vmp = vmp;
2193
2194 TAVOR_TNF_EXIT(tavor_rsrc_pd_handles_init);
2195 return (DDI_SUCCESS);
2196 }
2197
2198
2199 /*
2200 * tavor_rsrc_pd_handles_fini()
2201 * Context: Only called from attach() and/or detach() path contexts
2202 */
2203 static void
tavor_rsrc_pd_handles_fini(tavor_state_t * state,tavor_rsrc_sw_hdl_info_t * info)2204 tavor_rsrc_pd_handles_fini(tavor_state_t *state, tavor_rsrc_sw_hdl_info_t *info)
2205 {
2206 tavor_rsrc_pool_info_t *rsrc_pool;
2207
2208 TAVOR_TNF_ENTER(tavor_rsrc_pd_handles_fini);
2209
2210 ASSERT(state != NULL);
2211 ASSERT(info != NULL);
2212
2213 rsrc_pool = info->swi_rsrcpool;
2214
2215 /* Destroy the specially created UAR scratch table vmem arena */
2216 vmem_destroy(rsrc_pool->rsrc_vmp);
2217
2218 /* Destroy the "tavor_sw_pd_t" kmem_cache */
2219 tavor_rsrc_sw_handles_fini(state, info);
2220
2221 TAVOR_TNF_EXIT(tavor_rsrc_pd_handles_fini);
2222 }
2223
2224
2225 /*
2226 * tavor_rsrc_mbox_alloc()
2227 * Context: Only called from attach() path context
2228 */
2229 static int
tavor_rsrc_mbox_alloc(tavor_rsrc_pool_info_t * pool_info,uint_t num,tavor_rsrc_t * hdl)2230 tavor_rsrc_mbox_alloc(tavor_rsrc_pool_info_t *pool_info, uint_t num,
2231 tavor_rsrc_t *hdl)
2232 {
2233 tavor_rsrc_priv_mbox_t *priv;
2234 void *addr;
2235 caddr_t kaddr;
2236 uint64_t offset;
2237 size_t real_len, temp_len;
2238 int status;
2239
2240 TAVOR_TNF_ENTER(tavor_rsrc_mbox_alloc);
2241
2242 ASSERT(pool_info != NULL);
2243 ASSERT(hdl != NULL);
2244
2245 /* Get the private pointer for the mailboxes */
2246 priv = pool_info->rsrc_private;
2247 ASSERT(priv != NULL);
2248
2249 /*
2250 * Allocate a DMA handle for the mailbox. This will be used for
2251 * two purposes (potentially). First, it could be used below in
2252 * the call to ddi_dma_mem_alloc() - if the mailbox is to come from
2253 * system memory. Second, it is definitely used later to bind
2254 * the mailbox for DMA access from/by the hardware.
2255 */
2256 status = ddi_dma_alloc_handle(priv->pmb_dip, &priv->pmb_dmaattr,
2257 DDI_DMA_SLEEP, NULL, &hdl->tr_dmahdl);
2258 if (status != DDI_SUCCESS) {
2259 TNF_PROBE_1(tavor_rsrc_mbox_alloc_dmahdl_fail, TAVOR_TNF_ERROR,
2260 "", tnf_uint, status, status);
2261 TAVOR_TNF_EXIT(tavor_rsrc_mbox_alloc);
2262 return (DDI_FAILURE);
2263 }
2264
2265 /* Is mailbox in DDR memory or system memory? */
2266 if (pool_info->rsrc_loc == TAVOR_IN_DDR) {
2267 /* Use vmem_alloc() to get DDR address of mbox */
2268 hdl->tr_len = (num * pool_info->rsrc_quantum);
2269 addr = vmem_alloc(pool_info->rsrc_vmp, hdl->tr_len,
2270 VM_SLEEP);
2271 if (addr == NULL) {
2272 /* No more DDR available for mailbox entries */
2273 ddi_dma_free_handle(&hdl->tr_dmahdl);
2274 TNF_PROBE_0(tavor_rsrc_mbox_alloc_vma_fail,
2275 TAVOR_TNF_ERROR, "");
2276 TAVOR_TNF_EXIT(tavor_rsrc_mbox_alloc);
2277 return (DDI_FAILURE);
2278 }
2279 hdl->tr_acchdl = priv->pmb_acchdl;
2280
2281 /* Calculate kernel virtual address (from the DDR offset) */
2282 offset = ((uintptr_t)addr -
2283 (uintptr_t)pool_info->rsrc_ddr_offset);
2284 hdl->tr_addr = (void *)(uintptr_t)(offset +
2285 (uintptr_t)pool_info->rsrc_start);
2286
2287 } else { /* TAVOR_IN_SYSMEM */
2288
2289 /* Use ddi_dma_mem_alloc() to get memory for mailbox */
2290 temp_len = (num * pool_info->rsrc_quantum);
2291 status = ddi_dma_mem_alloc(hdl->tr_dmahdl, temp_len,
2292 &priv->pmb_devaccattr, priv->pmb_xfer_mode, DDI_DMA_SLEEP,
2293 NULL, &kaddr, &real_len, &hdl->tr_acchdl);
2294 if (status != DDI_SUCCESS) {
2295 /* No more sys memory available for mailbox entries */
2296 ddi_dma_free_handle(&hdl->tr_dmahdl);
2297 TNF_PROBE_0(tavor_rsrc_mbox_alloc_dma_memalloc_fail,
2298 TAVOR_TNF_ERROR, "");
2299 TAVOR_TNF_EXIT(tavor_rsrc_mbox_alloc);
2300 return (DDI_FAILURE);
2301 }
2302 hdl->tr_addr = (void *)kaddr;
2303 hdl->tr_len = real_len;
2304 }
2305
2306 TAVOR_TNF_EXIT(tavor_rsrc_mbox_alloc);
2307 return (DDI_SUCCESS);
2308 }
2309
2310
2311 /*
2312 * tavor_rsrc_mbox_free()
2313 * Context: Can be called from interrupt or base context.
2314 */
2315 static void
tavor_rsrc_mbox_free(tavor_rsrc_pool_info_t * pool_info,tavor_rsrc_t * hdl)2316 tavor_rsrc_mbox_free(tavor_rsrc_pool_info_t *pool_info, tavor_rsrc_t *hdl)
2317 {
2318 void *addr;
2319 uint64_t offset;
2320
2321 TAVOR_TNF_ENTER(tavor_rsrc_mbox_free);
2322
2323 ASSERT(pool_info != NULL);
2324 ASSERT(hdl != NULL);
2325
2326 /* Is mailbox in DDR memory or system memory? */
2327 if (pool_info->rsrc_loc == TAVOR_IN_DDR) {
2328
2329 /* Calculate the allocated address (the mbox's DDR offset) */
2330 offset = ((uintptr_t)hdl->tr_addr -
2331 (uintptr_t)pool_info->rsrc_start);
2332 addr = (void *)(uintptr_t)(offset +
2333 (uintptr_t)pool_info->rsrc_ddr_offset);
2334
2335 /* Use vmem_free() to free up DDR memory for mailbox */
2336 vmem_free(pool_info->rsrc_vmp, addr, hdl->tr_len);
2337
2338 } else { /* TAVOR_IN_SYSMEM */
2339
2340 /* Use ddi_dma_mem_free() to free up sys memory for mailbox */
2341 ddi_dma_mem_free(&hdl->tr_acchdl);
2342 }
2343
2344 /* Free the DMA handle for the mailbox */
2345 ddi_dma_free_handle(&hdl->tr_dmahdl);
2346
2347 TAVOR_TNF_EXIT(tavor_rsrc_mbox_free);
2348 }
2349
2350
2351 /*
2352 * tavor_rsrc_hw_entry_alloc()
2353 * Context: Can be called from interrupt or base context.
2354 */
2355 static int
tavor_rsrc_hw_entry_alloc(tavor_rsrc_pool_info_t * pool_info,uint_t num,uint_t num_align,ddi_acc_handle_t acc_handle,uint_t sleepflag,tavor_rsrc_t * hdl)2356 tavor_rsrc_hw_entry_alloc(tavor_rsrc_pool_info_t *pool_info, uint_t num,
2357 uint_t num_align, ddi_acc_handle_t acc_handle, uint_t sleepflag,
2358 tavor_rsrc_t *hdl)
2359 {
2360 void *addr;
2361 uint64_t offset;
2362 uint32_t align;
2363 int flag;
2364
2365 TAVOR_TNF_ENTER(tavor_rsrc_hw_entry_alloc);
2366
2367 ASSERT(pool_info != NULL);
2368 ASSERT(hdl != NULL);
2369
2370 /*
2371 * Tavor hardware entries (QPC, CQC, EQC, MPT, MTT, etc.) do not
2372 * use dma_handle (because they are in Tavor locally attached DDR
2373 * memory) and, generally, don't use the acc_handle (because the
2374 * entries are not directly accessed by software). The exceptions
2375 * to this rule are the UARPG and UDAV entries.
2376 */
2377
2378 /*
2379 * Use vmem_xalloc() to get a properly aligned pointer (based on
2380 * the number requested) to the HW entry(ies). This handles the
2381 * cases (for special QPCs and for RDB entries) where we need more
2382 * than one and need to ensure that they are properly aligned.
2383 */
2384 flag = (sleepflag == TAVOR_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
2385 hdl->tr_len = (num * pool_info->rsrc_quantum);
2386 align = (num_align * pool_info->rsrc_quantum);
2387 addr = vmem_xalloc(pool_info->rsrc_vmp, hdl->tr_len,
2388 align, 0, 0, NULL, NULL, flag | VM_FIRSTFIT);
2389 if (addr == NULL) {
2390 /* No more HW entries available */
2391 TNF_PROBE_0(tavor_rsrc_hw_entry_alloc_vmxa_fail,
2392 TAVOR_TNF_ERROR, "");
2393 TAVOR_TNF_EXIT(tavor_rsrc_hw_entry_alloc);
2394 return (DDI_FAILURE);
2395 }
2396
2397 /* If an access handle was provided, fill it in */
2398 if (acc_handle != 0) {
2399 hdl->tr_acchdl = acc_handle;
2400 }
2401
2402 /* Calculate vaddr and HW table index (from the DDR offset) */
2403 offset = ((uintptr_t)addr - (uintptr_t)pool_info->rsrc_ddr_offset);
2404 hdl->tr_addr = (void *)(uintptr_t)(offset +
2405 (uintptr_t)pool_info->rsrc_start);
2406 hdl->tr_indx = (offset >> pool_info->rsrc_shift);
2407
2408 TAVOR_TNF_EXIT(tavor_rsrc_hw_entry_alloc);
2409 return (DDI_SUCCESS);
2410 }
2411
2412
2413 /*
2414 * tavor_rsrc_hw_entry_free()
2415 * Context: Can be called from interrupt or base context.
2416 */
2417 static void
tavor_rsrc_hw_entry_free(tavor_rsrc_pool_info_t * pool_info,tavor_rsrc_t * hdl)2418 tavor_rsrc_hw_entry_free(tavor_rsrc_pool_info_t *pool_info, tavor_rsrc_t *hdl)
2419 {
2420 void *addr;
2421 uint64_t offset;
2422
2423 TAVOR_TNF_ENTER(tavor_rsrc_hw_entry_free);
2424
2425 ASSERT(pool_info != NULL);
2426 ASSERT(hdl != NULL);
2427
2428 /* Calculate the allocated address (the entry's DDR offset) */
2429 offset = ((uintptr_t)hdl->tr_addr - (uintptr_t)pool_info->rsrc_start);
2430 addr = (void *)(uintptr_t)(offset +
2431 (uintptr_t)pool_info->rsrc_ddr_offset);
2432
2433 /* Use vmem_xfree() to free up the HW table entry */
2434 vmem_xfree(pool_info->rsrc_vmp, addr, hdl->tr_len);
2435
2436 TAVOR_TNF_EXIT(tavor_rsrc_hw_entry_free);
2437 }
2438
2439
2440 /*
2441 * tavor_rsrc_swhdl_alloc()
2442 * Context: Can be called from interrupt or base context.
2443 */
2444 static int
tavor_rsrc_swhdl_alloc(tavor_rsrc_pool_info_t * pool_info,uint_t sleepflag,tavor_rsrc_t * hdl)2445 tavor_rsrc_swhdl_alloc(tavor_rsrc_pool_info_t *pool_info, uint_t sleepflag,
2446 tavor_rsrc_t *hdl)
2447 {
2448 void *addr;
2449 int flag;
2450
2451 TAVOR_TNF_ENTER(tavor_rsrc_swhdl_alloc);
2452
2453 ASSERT(pool_info != NULL);
2454 ASSERT(hdl != NULL);
2455
2456 /* Allocate the software handle structure */
2457 flag = (sleepflag == TAVOR_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
2458 addr = kmem_cache_alloc(pool_info->rsrc_private, flag);
2459 if (addr == NULL) {
2460 TNF_PROBE_0(tavor_rsrc_swhdl_alloc_kmca_fail, TAVOR_TNF_ERROR,
2461 "");
2462 TAVOR_TNF_EXIT(tavor_rsrc_swhdl_alloc);
2463 return (DDI_FAILURE);
2464 }
2465 hdl->tr_len = pool_info->rsrc_quantum;
2466 hdl->tr_addr = addr;
2467
2468 TAVOR_TNF_EXIT(tavor_rsrc_swhdl_alloc);
2469 return (DDI_SUCCESS);
2470 }
2471
2472
2473 /*
2474 * tavor_rsrc_swhdl_free()
2475 * Context: Can be called from interrupt or base context.
2476 */
2477 static void
tavor_rsrc_swhdl_free(tavor_rsrc_pool_info_t * pool_info,tavor_rsrc_t * hdl)2478 tavor_rsrc_swhdl_free(tavor_rsrc_pool_info_t *pool_info, tavor_rsrc_t *hdl)
2479 {
2480 TAVOR_TNF_ENTER(tavor_rsrc_swhdl_free);
2481
2482 ASSERT(pool_info != NULL);
2483 ASSERT(hdl != NULL);
2484
2485 /* Free the software handle structure */
2486 kmem_cache_free(pool_info->rsrc_private, hdl->tr_addr);
2487
2488 TAVOR_TNF_EXIT(tavor_rsrc_swhdl_free);
2489 }
2490
2491
2492 /*
2493 * tavor_rsrc_pdhdl_alloc()
2494 * Context: Can be called from interrupt or base context.
2495 */
2496 static int
tavor_rsrc_pdhdl_alloc(tavor_rsrc_pool_info_t * pool_info,uint_t sleepflag,tavor_rsrc_t * hdl)2497 tavor_rsrc_pdhdl_alloc(tavor_rsrc_pool_info_t *pool_info, uint_t sleepflag,
2498 tavor_rsrc_t *hdl)
2499 {
2500 tavor_pdhdl_t addr;
2501 void *tmpaddr;
2502 int flag, status;
2503
2504 TAVOR_TNF_ENTER(tavor_rsrc_pdhdl_alloc);
2505
2506 ASSERT(pool_info != NULL);
2507 ASSERT(hdl != NULL);
2508
2509 /* Allocate the software handle */
2510 status = tavor_rsrc_swhdl_alloc(pool_info, sleepflag, hdl);
2511 if (status != DDI_SUCCESS) {
2512 TNF_PROBE_0(tavor_rsrc_pdhdl_alloc_fail, TAVOR_TNF_ERROR, "");
2513 TAVOR_TNF_EXIT(tavor_rsrc_pdhdl_alloc);
2514 return (DDI_FAILURE);
2515 }
2516 addr = (tavor_pdhdl_t)hdl->tr_addr;
2517 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*addr))
2518
2519 /* Allocate a PD number for the handle */
2520 flag = (sleepflag == TAVOR_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
2521 tmpaddr = vmem_alloc(pool_info->rsrc_vmp, 1, flag);
2522 if (tmpaddr == NULL) {
2523 /* No more PD number entries available */
2524 tavor_rsrc_swhdl_free(pool_info, hdl);
2525 TNF_PROBE_0(tavor_rsrc_pdhdl_alloc_vma_fail,
2526 TAVOR_TNF_ERROR, "");
2527 TAVOR_TNF_EXIT(tavor_rsrc_pdhdl_alloc);
2528 return (DDI_FAILURE);
2529 }
2530 addr->pd_pdnum = (uint32_t)(uintptr_t)tmpaddr;
2531 addr->pd_rsrcp = hdl;
2532 hdl->tr_indx = addr->pd_pdnum;
2533
2534 TAVOR_TNF_EXIT(tavor_rsrc_pdhdl_alloc);
2535 return (DDI_SUCCESS);
2536 }
2537
2538
2539 /*
2540 * tavor_rsrc_pdhdl_free()
2541 * Context: Can be called from interrupt or base context.
2542 */
2543 static void
tavor_rsrc_pdhdl_free(tavor_rsrc_pool_info_t * pool_info,tavor_rsrc_t * hdl)2544 tavor_rsrc_pdhdl_free(tavor_rsrc_pool_info_t *pool_info, tavor_rsrc_t *hdl)
2545 {
2546 TAVOR_TNF_ENTER(tavor_rsrc_pdhdl_free);
2547
2548 ASSERT(pool_info != NULL);
2549 ASSERT(hdl != NULL);
2550
2551 /* Use vmem_free() to free up the PD number */
2552 vmem_free(pool_info->rsrc_vmp, (void *)(uintptr_t)hdl->tr_indx, 1);
2553
2554 /* Free the software handle structure */
2555 tavor_rsrc_swhdl_free(pool_info, hdl);
2556
2557 TAVOR_TNF_EXIT(tavor_rsrc_pdhdl_free);
2558 }
2559
2560
2561 /*
2562 * tavor_rsrc_pdhdl_constructor()
2563 * Context: Can be called from interrupt or base context.
2564 */
2565 /* ARGSUSED */
2566 static int
tavor_rsrc_pdhdl_constructor(void * pd,void * priv,int flags)2567 tavor_rsrc_pdhdl_constructor(void *pd, void *priv, int flags)
2568 {
2569 tavor_pdhdl_t pdhdl;
2570 tavor_state_t *state;
2571
2572 TAVOR_TNF_ENTER(tavor_rsrc_pdhdl_constructor);
2573
2574 pdhdl = (tavor_pdhdl_t)pd;
2575 state = (tavor_state_t *)priv;
2576
2577 mutex_init(&pdhdl->pd_lock, NULL, MUTEX_DRIVER,
2578 DDI_INTR_PRI(state->ts_intrmsi_pri));
2579
2580 TAVOR_TNF_EXIT(tavor_rsrc_pdhdl_constructor);
2581 return (DDI_SUCCESS);
2582 }
2583
2584
2585 /*
2586 * tavor_rsrc_pdhdl_destructor()
2587 * Context: Can be called from interrupt or base context.
2588 */
2589 /* ARGSUSED */
2590 static void
tavor_rsrc_pdhdl_destructor(void * pd,void * priv)2591 tavor_rsrc_pdhdl_destructor(void *pd, void *priv)
2592 {
2593 tavor_pdhdl_t pdhdl;
2594
2595 TAVOR_TNF_ENTER(tavor_rsrc_pdhdl_destructor);
2596
2597 pdhdl = (tavor_pdhdl_t)pd;
2598
2599 mutex_destroy(&pdhdl->pd_lock);
2600
2601 TAVOR_TNF_EXIT(tavor_rsrc_pdhdl_destructor);
2602 }
2603
2604
2605 /*
2606 * tavor_rsrc_cqhdl_constructor()
2607 * Context: Can be called from interrupt or base context.
2608 */
2609 /* ARGSUSED */
2610 static int
tavor_rsrc_cqhdl_constructor(void * cq,void * priv,int flags)2611 tavor_rsrc_cqhdl_constructor(void *cq, void *priv, int flags)
2612 {
2613 tavor_cqhdl_t cqhdl;
2614 tavor_state_t *state;
2615
2616 TAVOR_TNF_ENTER(tavor_rsrc_cqhdl_constructor);
2617
2618 cqhdl = (tavor_cqhdl_t)cq;
2619 state = (tavor_state_t *)priv;
2620
2621 mutex_init(&cqhdl->cq_lock, NULL, MUTEX_DRIVER,
2622 DDI_INTR_PRI(state->ts_intrmsi_pri));
2623 mutex_init(&cqhdl->cq_wrid_wqhdr_lock, NULL, MUTEX_DRIVER,
2624 DDI_INTR_PRI(state->ts_intrmsi_pri));
2625
2626 TAVOR_TNF_EXIT(tavor_rsrc_cqhdl_constructor);
2627 return (DDI_SUCCESS);
2628 }
2629
2630
2631 /*
2632 * tavor_rsrc_cqhdl_destructor()
2633 * Context: Can be called from interrupt or base context.
2634 */
2635 /* ARGSUSED */
2636 static void
tavor_rsrc_cqhdl_destructor(void * cq,void * priv)2637 tavor_rsrc_cqhdl_destructor(void *cq, void *priv)
2638 {
2639 tavor_cqhdl_t cqhdl;
2640
2641 TAVOR_TNF_ENTER(tavor_rsrc_cqhdl_destructor);
2642
2643 cqhdl = (tavor_cqhdl_t)cq;
2644
2645 mutex_destroy(&cqhdl->cq_wrid_wqhdr_lock);
2646 mutex_destroy(&cqhdl->cq_lock);
2647
2648 TAVOR_TNF_EXIT(tavor_rsrc_cqhdl_destructor);
2649 }
2650
2651
2652 /*
2653 * tavor_rsrc_qphdl_constructor()
2654 * Context: Can be called from interrupt or base context.
2655 */
2656 /* ARGSUSED */
2657 static int
tavor_rsrc_qphdl_constructor(void * qp,void * priv,int flags)2658 tavor_rsrc_qphdl_constructor(void *qp, void *priv, int flags)
2659 {
2660 tavor_qphdl_t qphdl;
2661 tavor_state_t *state;
2662
2663 TAVOR_TNF_ENTER(tavor_rsrc_qphdl_constructor);
2664
2665 qphdl = (tavor_qphdl_t)qp;
2666 state = (tavor_state_t *)priv;
2667
2668 mutex_init(&qphdl->qp_lock, NULL, MUTEX_DRIVER,
2669 DDI_INTR_PRI(state->ts_intrmsi_pri));
2670
2671 TAVOR_TNF_EXIT(tavor_rsrc_qphdl_constructor);
2672 return (DDI_SUCCESS);
2673 }
2674
2675
2676 /*
2677 * tavor_rsrc_qphdl_destructor()
2678 * Context: Can be called from interrupt or base context.
2679 */
2680 /* ARGSUSED */
2681 static void
tavor_rsrc_qphdl_destructor(void * qp,void * priv)2682 tavor_rsrc_qphdl_destructor(void *qp, void *priv)
2683 {
2684 tavor_qphdl_t qphdl;
2685
2686 TAVOR_TNF_ENTER(tavor_rsrc_qphdl_destructor);
2687
2688 qphdl = (tavor_qphdl_t)qp;
2689
2690 mutex_destroy(&qphdl->qp_lock);
2691
2692 TAVOR_TNF_ENTER(tavor_rsrc_qphdl_destructor);
2693 }
2694
2695
2696 /*
2697 * tavor_rsrc_srqhdl_constructor()
2698 * Context: Can be called from interrupt or base context.
2699 */
2700 /* ARGSUSED */
2701 static int
tavor_rsrc_srqhdl_constructor(void * srq,void * priv,int flags)2702 tavor_rsrc_srqhdl_constructor(void *srq, void *priv, int flags)
2703 {
2704 tavor_srqhdl_t srqhdl;
2705 tavor_state_t *state;
2706
2707 TAVOR_TNF_ENTER(tavor_rsrc_srqhdl_constructor);
2708
2709 srqhdl = (tavor_srqhdl_t)srq;
2710 state = (tavor_state_t *)priv;
2711
2712 mutex_init(&srqhdl->srq_lock, NULL, MUTEX_DRIVER,
2713 DDI_INTR_PRI(state->ts_intrmsi_pri));
2714
2715 TAVOR_TNF_EXIT(tavor_rsrc_srqhdl_constructor);
2716 return (DDI_SUCCESS);
2717 }
2718
2719
2720 /*
2721 * tavor_rsrc_srqhdl_destructor()
2722 * Context: Can be called from interrupt or base context.
2723 */
2724 /* ARGSUSED */
2725 static void
tavor_rsrc_srqhdl_destructor(void * srq,void * priv)2726 tavor_rsrc_srqhdl_destructor(void *srq, void *priv)
2727 {
2728 tavor_srqhdl_t srqhdl;
2729
2730 TAVOR_TNF_ENTER(tavor_rsrc_srqhdl_destructor);
2731
2732 srqhdl = (tavor_srqhdl_t)srq;
2733
2734 mutex_destroy(&srqhdl->srq_lock);
2735
2736 TAVOR_TNF_EXIT(tavor_rsrc_srqhdl_destructor);
2737 }
2738
2739
2740 /*
2741 * tavor_rsrc_refcnt_constructor()
2742 * Context: Can be called from interrupt or base context.
2743 */
2744 /* ARGSUSED */
2745 static int
tavor_rsrc_refcnt_constructor(void * rc,void * priv,int flags)2746 tavor_rsrc_refcnt_constructor(void *rc, void *priv, int flags)
2747 {
2748 tavor_sw_refcnt_t *refcnt;
2749 tavor_state_t *state;
2750
2751 TAVOR_TNF_ENTER(tavor_rsrc_refcnt_constructor);
2752
2753 refcnt = (tavor_sw_refcnt_t *)rc;
2754 state = (tavor_state_t *)priv;
2755
2756 mutex_init(&refcnt->swrc_lock, NULL, MUTEX_DRIVER,
2757 DDI_INTR_PRI(state->ts_intrmsi_pri));
2758
2759 TAVOR_TNF_EXIT(tavor_rsrc_refcnt_constructor);
2760 return (DDI_SUCCESS);
2761 }
2762
2763
2764 /*
2765 * tavor_rsrc_refcnt_destructor()
2766 * Context: Can be called from interrupt or base context.
2767 */
2768 /* ARGSUSED */
2769 static void
tavor_rsrc_refcnt_destructor(void * rc,void * priv)2770 tavor_rsrc_refcnt_destructor(void *rc, void *priv)
2771 {
2772 tavor_sw_refcnt_t *refcnt;
2773
2774 TAVOR_TNF_ENTER(tavor_rsrc_refcnt_destructor);
2775
2776 refcnt = (tavor_sw_refcnt_t *)rc;
2777
2778 mutex_destroy(&refcnt->swrc_lock);
2779
2780 TAVOR_TNF_ENTER(tavor_rsrc_refcnt_destructor);
2781 }
2782
2783
2784 /*
2785 * tavor_rsrc_ahhdl_constructor()
2786 * Context: Can be called from interrupt or base context.
2787 */
2788 /* ARGSUSED */
2789 static int
tavor_rsrc_ahhdl_constructor(void * ah,void * priv,int flags)2790 tavor_rsrc_ahhdl_constructor(void *ah, void *priv, int flags)
2791 {
2792 tavor_ahhdl_t ahhdl;
2793 tavor_state_t *state;
2794
2795 TAVOR_TNF_ENTER(tavor_rsrc_ahhdl_constructor);
2796
2797 ahhdl = (tavor_ahhdl_t)ah;
2798 state = (tavor_state_t *)priv;
2799
2800 mutex_init(&ahhdl->ah_lock, NULL, MUTEX_DRIVER,
2801 DDI_INTR_PRI(state->ts_intrmsi_pri));
2802
2803 TAVOR_TNF_EXIT(tavor_rsrc_ahhdl_constructor);
2804 return (DDI_SUCCESS);
2805 }
2806
2807
2808 /*
2809 * tavor_rsrc_ahhdl_destructor()
2810 * Context: Can be called from interrupt or base context.
2811 */
2812 /* ARGSUSED */
2813 static void
tavor_rsrc_ahhdl_destructor(void * ah,void * priv)2814 tavor_rsrc_ahhdl_destructor(void *ah, void *priv)
2815 {
2816 tavor_ahhdl_t ahhdl;
2817
2818 TAVOR_TNF_ENTER(tavor_rsrc_ahhdl_destructor);
2819
2820 ahhdl = (tavor_ahhdl_t)ah;
2821
2822 mutex_destroy(&ahhdl->ah_lock);
2823
2824 TAVOR_TNF_ENTER(tavor_rsrc_ahhdl_destructor);
2825 }
2826
2827
2828 /*
2829 * tavor_rsrc_mrhdl_constructor()
2830 * Context: Can be called from interrupt or base context.
2831 */
2832 /* ARGSUSED */
2833 static int
tavor_rsrc_mrhdl_constructor(void * mr,void * priv,int flags)2834 tavor_rsrc_mrhdl_constructor(void *mr, void *priv, int flags)
2835 {
2836 tavor_mrhdl_t mrhdl;
2837 tavor_state_t *state;
2838
2839 TAVOR_TNF_ENTER(tavor_rsrc_mrhdl_constructor);
2840
2841 mrhdl = (tavor_mrhdl_t)mr;
2842 state = (tavor_state_t *)priv;
2843
2844 mutex_init(&mrhdl->mr_lock, NULL, MUTEX_DRIVER,
2845 DDI_INTR_PRI(state->ts_intrmsi_pri));
2846
2847 TAVOR_TNF_EXIT(tavor_rsrc_mrhdl_constructor);
2848 return (DDI_SUCCESS);
2849 }
2850
2851
2852 /*
2853 * tavor_rsrc_mrhdl_destructor()
2854 * Context: Can be called from interrupt or base context.
2855 */
2856 /* ARGSUSED */
2857 static void
tavor_rsrc_mrhdl_destructor(void * mr,void * priv)2858 tavor_rsrc_mrhdl_destructor(void *mr, void *priv)
2859 {
2860 tavor_mrhdl_t mrhdl;
2861
2862 TAVOR_TNF_ENTER(tavor_rsrc_mrhdl_destructor);
2863
2864 mrhdl = (tavor_mrhdl_t)mr;
2865
2866 mutex_destroy(&mrhdl->mr_lock);
2867
2868 TAVOR_TNF_ENTER(tavor_rsrc_mrhdl_destructor);
2869 }
2870
2871
2872 /*
2873 * tavor_rsrc_mcg_entry_get_size()
2874 */
2875 static int
tavor_rsrc_mcg_entry_get_size(tavor_state_t * state,uint_t * mcg_size_shift)2876 tavor_rsrc_mcg_entry_get_size(tavor_state_t *state, uint_t *mcg_size_shift)
2877 {
2878 uint_t num_qp_per_mcg, max_qp_per_mcg, log2;
2879
2880 TAVOR_TNF_ENTER(tavor_rsrc_mcg_entry_get_size);
2881
2882 /*
2883 * Round the configured number of QP per MCG to next larger
2884 * power-of-2 size and update.
2885 */
2886 num_qp_per_mcg = state->ts_cfg_profile->cp_num_qp_per_mcg + 8;
2887 log2 = highbit(num_qp_per_mcg);
2888 if ((num_qp_per_mcg & (num_qp_per_mcg - 1)) == 0) {
2889 log2 = log2 - 1;
2890 }
2891 state->ts_cfg_profile->cp_num_qp_per_mcg = (1 << log2) - 8;
2892
2893 /* Now make sure number of QP per MCG makes sense */
2894 num_qp_per_mcg = state->ts_cfg_profile->cp_num_qp_per_mcg;
2895 max_qp_per_mcg = (1 << state->ts_devlim.log_max_qp_mcg);
2896 if (num_qp_per_mcg > max_qp_per_mcg) {
2897 TNF_PROBE_1(tavor_rsrc_mcg_getsz_toomany_qppermcg_fail,
2898 TAVOR_TNF_ERROR, "", tnf_uint, maxqpmcg, max_qp_per_mcg);
2899 TAVOR_TNF_EXIT(tavor_rsrc_mcg_entry_get_size);
2900 return (DDI_FAILURE);
2901 }
2902
2903 /* Return the (shift) size of an individual MCG HW entry */
2904 *mcg_size_shift = log2 + 2;
2905
2906 TAVOR_TNF_EXIT(tavor_rsrc_mcg_entry_get_size);
2907 return (DDI_SUCCESS);
2908 }
2909