/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Tavor Resource Management Routines
*
* Implements all the routines necessary for setup, teardown, and
* by Tavor hardware or which live in Tavor's direct attached DDR memory.
*/
#include <sys/sysmacros.h>
/*
* The following routines are used for initializing and destroying
* the resource pools used by the Tavor resource allocation routines.
* They consist of four classes of object:
*
* Mailboxes: The "In" and "Out" mailbox types are used by the Tavor
* command interface routines. Mailboxes are used to pass information
* back and forth to the Tavor firmware. Either type of mailbox may
* be allocated from Tavor's direct attached DDR memory or from system
* memory (although currently all "In" mailboxes are in DDR and all "out"
* mailboxes come from system memory.
*
* HW entry objects: These objects represent resources required by the Tavor
* hardware. These objects include things like Queue Pair contexts (QPC),
* Completion Queue contexts (CQC), Event Queue contexts (EQC), RDB (for
* Protection Table entries (MPT), Memory Translation Table entries (MTT).
*
* What these objects all have in common is that they are each required
* to come from DDR memory, they are always allocated from tables, and
* they are not to be directly accessed (read or written) by driver
* software.
* One notable exceptions to this rule are the Extended QP contexts (EQPC),
* and the UAR scratch area (UAR_SCR), both of which are not directly
* accessible through the Tavor resource allocation routines, but both
* of which are also required to reside in DDR memory and are not to be
* manipulated by driver software (they are privately managed by Tavor
* hardware).
* The other notable exceptions are the UAR pages (UAR_PG) which are
* allocated from the UAR address space rather than DDR, and the UD
* address vectors (UDAV) which are similar to the common object types
* with the major difference being that UDAVs _are_ directly read and
* written by driver software.
*
* SW handle objects: These objects represent resources required by Tavor
* driver software. They are primarily software tracking structures,
* which are allocated from system memory (using kmem_cache). Several of
* the objects have both a "constructor" and "destructor" method
* associated with them (see below).
*
* Protection Domain (PD) handle objects: These objects are very much like
* a SW handle object with the notable difference that all PD handle
* objects have an actual Protection Domain number (PD) associated with
* vmem_arena specifically set aside for this purpose.
*/
/*
* The following routines are used for allocating and freeing the specific
* types of objects described above from their associated resource pools.
*/
tavor_rsrc_t *hdl);
tavor_rsrc_t *hdl);
tavor_rsrc_t *hdl);
tavor_rsrc_t *hdl);
/*
* The following routines are the constructors and destructors for several
* of the SW handle type objects. For certain types of SW handles objects
* (all of which are implemented using kmem_cache), we need to do some
* special field initialization (specifically, mutex_init/destroy). These
* routines enable that init and teardown.
*/
/*
* Special routine to calculate and return the size of a MCG object based
* on current driver configuration (specifically, the number of QP per MCG
* that has been configured.
*/
/*
* tavor_rsrc_alloc()
*
* Context: Can be called from interrupt or base context.
* The "sleepflag" parameter is used by all object allocators to
* determine whether to SLEEP for resources or not.
*/
int
{
/*
* Allocate space for the object used to track the resource handle
*/
flag);
if (tmp_rsrc_hdl == NULL) {
return (DDI_FAILURE);
}
/*
* Set rsrc_hdl type. This is later used by the tavor_rsrc_free call
* to know what type of resource is being freed.
*/
/*
* Depending on resource type, call the appropriate alloc routine
*/
case TAVOR_IN_MBOX:
case TAVOR_OUT_MBOX:
case TAVOR_INTR_IN_MBOX:
case TAVOR_INTR_OUT_MBOX:
break;
case TAVOR_QPC:
case TAVOR_CQC:
case TAVOR_SRQC:
case TAVOR_EQC:
case TAVOR_RDB:
/*
* Because these objects are NOT accessed by Tavor driver
* software, we set the acc_handle parameter to zero. But
* if they are allocated in multiples, we specify here that
* they must be aligned on a more restrictive boundary.
*/
break;
case TAVOR_MPT:
/*
* Because these MPT objects are sometimes accessed by Tavor
* driver software (FMR), we set the acc_handle parameter. But
* if they are allocated in multiples, we specify here that
* they must be aligned on a more restrictive boundary.
*/
break;
case TAVOR_MCG:
/*
* Tavor MCG entries are also NOT accessed by Tavor driver
* software, but because MCG entries do not have the same
* alignnment restrictions we loosen the constraint here.
*/
break;
case TAVOR_MTT:
case TAVOR_UDAV:
/*
* Because MTT segments are among the few HW resources that
* may be allocated in odd numbers, we specify a less
* restrictive alignment than for the above resources.
*
* Also because both UDAV and MTT segment objects are read
* acc_handle parameter to point to the ddi_acc_handle_t for
* the Tavor DDR memory.
*/
break;
case TAVOR_UARPG:
/*
* Because UAR pages are written by Tavor driver software (for
* doorbells), we set the acc_handle parameter to point to
* the ddi_acc_handle_t for the Tavor UAR memory.
*/
break;
case TAVOR_MRHDL:
case TAVOR_EQHDL:
case TAVOR_CQHDL:
case TAVOR_SRQHDL:
case TAVOR_AHHDL:
case TAVOR_QPHDL:
case TAVOR_REFCNT:
break;
case TAVOR_PDHDL:
break;
default:
TAVOR_TNF_ERROR, "");
break;
}
/*
* If the resource allocation failed, then free the special resource
* tracking structure and return failure. Otherwise return the
* handle for the resource tracking structure.
*/
if (status != DDI_SUCCESS) {
tmp_rsrc_hdl = NULL;
return (DDI_FAILURE);
} else {
*hdl = tmp_rsrc_hdl;
return (DDI_SUCCESS);
}
}
/*
* tavor_rsrc_free()
* Context: Can be called from interrupt or base context.
*/
void
{
/*
* Depending on resource type, call the appropriate free routine
*/
case TAVOR_IN_MBOX:
case TAVOR_OUT_MBOX:
case TAVOR_INTR_IN_MBOX:
case TAVOR_INTR_OUT_MBOX:
break;
case TAVOR_QPC:
case TAVOR_CQC:
case TAVOR_SRQC:
case TAVOR_EQC:
case TAVOR_RDB:
case TAVOR_MCG:
case TAVOR_MPT:
case TAVOR_MTT:
case TAVOR_UDAV:
case TAVOR_UARPG:
break;
case TAVOR_MRHDL:
case TAVOR_EQHDL:
case TAVOR_CQHDL:
case TAVOR_SRQHDL:
case TAVOR_AHHDL:
case TAVOR_QPHDL:
case TAVOR_REFCNT:
break;
case TAVOR_PDHDL:
break;
default:
TAVOR_TNF_ERROR, "");
break;
}
/*
* Free the special resource tracking structure, set the handle to
* NULL, and return.
*/
}
/*
* tavor_rsrc_init_phase1()
*
* Completes the first phase of Tavor resource/configuration init.
* This involves creating the kmem_cache for the "tavor_rsrc_t"
* structs, allocating the space for the resource pool handles,
* and setting up the "Out" mailboxes.
*
* When this function completes, the Tavor driver is ready to
* post the following commands which return information only in the
* "Out" mailbox: QUERY_DDR, QUERY_FW, QUERY_DEV_LIM, and QUERY_ADAPTER
* If any of these commands are to be posted at this time, they must be
* done so only when "spinning" (as the outstanding command list and
* EQ setup code has not yet run)
*
* Context: Only called from attach() path context
*/
int
{
int status;
/* This is where Phase 1 of resource initialization begins */
/* Build kmem cache name from Tavor instance */
/*
* Create the kmem_cache for "tavor_rsrc_t" structures
* (kmem_cache_create will SLEEP until successful)
*/
/*
* Allocate an array of tavor_rsrc_pool_info_t's (used in all
* subsequent resource allocations)
*/
sizeof (tavor_rsrc_pool_info_t), KM_SLEEP);
/*
* Initialize the resource pool for "Out" mailboxes. Notice that
* the number of "Out" mailboxes, their size, and their location
* (DDR or system memory) is configurable. By default, however,
* all "Out" mailboxes are located in system memory only (because
* they are primarily read from and never written to)
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp1_fail;
}
/*
* Initialize the Tavor "Out" mailbox list. This step actually uses
* the tavor_rsrc_alloc() for TAVOR_OUT_MBOX to preallocate the
* "Out" mailboxes, bind them for DMA access, and arrange them into
* an easily accessed fast-allocation mechanism (see tavor_cmd.c
* for more details)
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp1_fail;
}
/*
* Initialize the resource pool for interrupt "Out" mailboxes. Notice
* that the number of interrupt "Out" mailboxes, their size, and their
* location (DDR or system memory) is configurable. By default,
* however, all interrupt "Out" mailboxes are located in system memory
* only (because they are primarily read from and never written to)
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp1_fail;
}
/*
* Initialize the Tavor "Out" mailbox list. This step actually uses
* the tavor_rsrc_alloc() for TAVOR_OUT_MBOX to preallocate the
* "Out" mailboxes, bind them for DMA access, and arrange them into
* an easily accessed fast-allocation mechanism (see tavor_cmd.c
* for more details)
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp1_fail;
}
return (DDI_SUCCESS);
return (status);
}
/*
* tavor_rsrc_init_phase2()
* Context: Only called from attach() path context
*/
int
{
int status;
/* Phase 2 initialization begins where Phase 1 left off */
/*
* Calculate the extent of the DDR size and portion of which that
* is already reserved for Tavor firmware. (Note: this information
* is available because the QUERY_DDR and QUERY_FW commands have
* been posted to Tavor firmware prior to calling this routine)
*/
/* Build the DDR vmem arena name from Tavor instance */
/*
* Do a vmem_create for the entire DDR range (not including the
* portion consumed by Tavor firmware). This creates the vmem arena
* from which all other DDR objects (specifically, tables of HW
* entries) will be allocated.
*/
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Initialize the resource pools for all objects that exist in
* Tavor DDR memory. This includes ("In") mailboxes, context tables
* (QPC, CQC, EQC, etc...), and other miscellaneous HW objects.
*/
/*
* Initialize the resource pool for the MPT table entries. Notice
* that the number of MPTs is configurable. The configured value must
* be less that the maximum value (obtained from the QUERY_DEV_LIM
* command) or the initialization will fail. Note also that a certain
* number of MPTs must be set aside for Tavor firmware use.
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Initialize the resource pool for the MTT table entries. Notice
* that the number of MTTs is configurable. The configured value must
* be less that the maximum value (obtained from the QUERY_DEV_LIM
* command) or the initialization will fail. Note also that a certain
* number of MTT segments must be set aside for Tavor firmware use.
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Initialize the resource pool for the QPC table entries. Notice
* that the number of QPs is configurable. The configured value must
* be less that the maximum value (obtained from the QUERY_DEV_LIM
* command) or the initialization will fail. Note also that a certain
* number of QP contexts must be set aside for Tavor firmware use.
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Initialize the resource pool for the RDB table entries. Notice
* that the number of RDBs is configurable. The configured value must
* be less that the maximum value (obtained from the QUERY_DEV_LIM
* command) or the initialization will fail.
*/
num_prealloc = 0;
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Initialize the resource pool for the CQC table entries. Notice
* that the number of CQs is configurable. The configured value must
* be less that the maximum value (obtained from the QUERY_DEV_LIM
* command) or the initialization will fail. Note also that a certain
* number of CQ contexts must be set aside for Tavor firmware use.
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Initialize the resource pool for the Extended QPC table entries.
* Notice that the number of EQPCs must be the same as the number
* of QP contexts. So the initialization is constructed in a
* similar way as above (for TAVOR_QPC). One notable difference
* here, however, is that by setting the rsrc_quantum field to
* zero (indicating a zero-sized object) we indicate that the
* object is not allocatable. The EQPC table is, in fact, managed
* internally by the hardware and it is, therefore, unnecessary to
* initialize an additional vmem_arena for this type of object.
*/
num_prealloc = 0;
rsrc_pool->rsrc_shift = 0;
rsrc_pool->rsrc_quantum = 0;
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Initialize the resource pool for the UD address vector table
* entries. Notice that the number of UDAVs is configurable. The
* configured value must be less that the maximum value (obtained
* from the QUERY_DEV_LIM command) or the initialization will fail.
*/
num_prealloc = 0;
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Initialize the resource pool for the UAR scratch table entries.
* Notice that the number of UARSCRs is configurable. The configured
* value must be less that the maximum value (obtained from the
* QUERY_DEV_LIM command) or the initialization will fail.
* Like the EQPCs above, UARSCR objects are not allocatable. The
* UARSCR table is also managed internally by the hardware and it
* is, therefore, unnecessary to initialize an additional vmem_arena
* for this type of object. We indicate this by setting the
* rsrc_quantum field to zero (indicating a zero-sized object).
*/
PAGESHIFT));
num_prealloc = 0;
rsrc_pool->rsrc_shift = 0;
rsrc_pool->rsrc_quantum = 0;
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Initialize the resource pool for the SRQC table entries. Notice
* that the number of SRQs is configurable. The configured value must
* be less that the maximum value (obtained from the QUERY_DEV_LIM
* command) or the initialization will fail. Note also that a certain
* number of SRQ contexts must be set aside for Tavor firmware use.
*
* Note: We only allocate these resources if SRQ is enabled in the
* config profile; see below.
*/
/*
* SRQ support is configurable. Only if SRQ is enabled (the default)
* do we actually try to configure these resources. Otherwise, we
* simply set the cleanup level and continue on to the next resource
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
}
/*
* Initialize the resource pool for "In" mailboxes. Notice that
* the number of "In" mailboxes, their size, and their location
* (DDR or system memory) is configurable. By default, however,
* all "In" mailboxes are located in system memory only (because
* they are primarily written to and rarely read from)
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Initialize the Tavor "In" mailbox list. This step actually uses
* the tavor_rsrc_alloc() for TAVOR_IN_MBOX to preallocate the
* "In" mailboxes, bind them for DMA access, and arrange them into
* an easily accessed fast-allocation mechanism (see tavor_cmd.c
* for more details)
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Initialize the resource pool for interrupt "In" mailboxes. Notice
* that the number of interrupt "In" mailboxes, their size, and their
* location (DDR or system memory) is configurable. By default,
* however, all interrupt "In" mailboxes are located in system memory
* only (because they are primarily written to and rarely read from)
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Initialize the Tavor interrupt "In" mailbox list. This step
* actually uses the tavor_rsrc_alloc() for TAVOR_IN_MBOX to
* preallocate the interrupt "In" mailboxes, bind them for DMA access,
* and arrange them into an easily accessed fast-allocation mechanism
* (see tavor_cmd.c for more details)
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Initialize the Tavor command handling interfaces. This step
* sets up the outstanding command tracking mechanism for easy access
* and fast allocation (see tavor_cmd.c for more details).
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Calculate (and validate) the size of Multicast Group (MCG) entries
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Initialize the resource pool for the MCG table entries. Notice
* that the number of MCGs is configurable. The configured value must
* be less that the maximum value (obtained from the QUERY_DEV_LIM
* command) or the initialization will fail. Note also that a certain
* number of MCGs must be set aside for Tavor firmware use (they
* correspond to the number of MCGs used by the internal hash
* function.
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Initialize the resource pool for the EQC table entries. Notice
* that the number of EQs is hardcoded. The hardcoded value should
* be less that the maximum value (obtained from the QUERY_DEV_LIM
* command) or the initialization will fail.
*/
num = TAVOR_NUM_EQ;
num_prealloc = 0;
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Initialize the resource pools for all objects that exist in
* system memory. This includes PD handles, MR handle, EQ handles,
* QP handles, etc. These objects are almost entirely managed using
* kmem_cache routines. (See comment above for more detail)
*/
/*
* Initialize the resource pool for the PD handles. Notice
* that the number of PDHDLs is configurable. The configured value
* must be less that the maximum value (obtained from the QUERY_DEV_LIM
* command) or the initialization will fail. Note also that the PD
* handle has constructor and destructor methods associated with it.
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Initialize the resource pool for the MR handles. Notice
* that the number of MRHDLs is configurable. The configured value
* must be less that the maximum value (obtained from the QUERY_DEV_LIM
* command) or the initialization will fail.
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Initialize the resource pool for the EQ handles. Notice
* that the number of EQHDLs is hardcoded. The hardcoded value
* should be less that the maximum value (obtained from the
* QUERY_DEV_LIM command) or the initialization will fail.
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Initialize the resource pool for the CQ handles. Notice
* that the number of CQHDLs is configurable. The configured value
* must be less that the maximum value (obtained from the QUERY_DEV_LIM
* command) or the initialization will fail. Note also that the CQ
* handle has constructor and destructor methods associated with it.
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Save away the pointer to the central list of CQ handle pointers
* This this is used as a mechanism to enable fast CQnumber-to-CQhandle
* lookup during EQ event processing. The table is a list of
* tavor_cqhdl_t allocated by the above routine because of the
* TAVOR_SWHDL_TABLE_INIT flag. The table has as many tavor_cqhdl_t
* as the number of CQs.
*/
/*
* Initialize the resource pool for the SRQ handles. Notice
* that the number of SRQHDLs is configurable. The configured value
* must be less that the maximum value (obtained from the QUERY_DEV_LIM
* command) or the initialization will fail. Note also that the SRQ
* handle has constructor and destructor methods associated with it.
*
* Note: We only allocate these resources if SRQ is enabled in the
* config profile; see below.
*/
/*
* SRQ support is configurable. Only if SRQ is enabled (the default)
* do we actually try to configure these resources. Otherwise, we
* simply set the cleanup level and continue on to the next resource
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Save away the pointer to the central list of SRQ handle
* pointers This this is used as a mechanism to enable fast
* SRQnumber-to-SRQhandle lookup. The table is a list of
* tavor_srqhdl_t allocated by the above routine because of the
* TAVOR_SWHDL_TABLE_INIT flag. The table has as many
* tavor_srqhdl_t as the number of SRQs.
*/
}
/*
* Initialize the resource pool for the address handles. Notice
* that the number of AHHDLs is configurable. The configured value
* must be less that the maximum value (obtained from the QUERY_DEV_LIM
* command) or the initialization will fail.
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Initialize the resource pool for the QP handles. Notice
* that the number of QPHDLs is configurable. The configured value
* must be less that the maximum value (obtained from the QUERY_DEV_LIM
* command) or the initialization will fail. Note also that the QP
* handle has constructor and destructor methods associated with it.
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Save away the pointer to the central list of QP handle pointers
* This this is used as a mechanism to enable fast QPnumber-to-QPhandle
* lookup during CQ event processing. The table is a list of
* tavor_qphdl_t allocated by the above routine because of the
* TAVOR_SWHDL_TABLE_INIT flag. The table has as many tavor_qphdl_t
* as the number of QPs.
*/
/*
* Initialize the resource pool for the reference count handles.
* Notice that the number of REFCNTs is configurable, but it's value
* is set to the number of MPTs. Since REFCNTs are used to support
* shared memory regions, it is possible that we might require as
* one REFCNT for every MPT.
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Initialize the resource pool for the MCG handles. Notice that for
* these MCG handles, we are allocating a table of structures (used to
* keep track of the MCG entries that are being written to hardware
*/
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
/*
* Initialize the resource pools for all objects that exist in
* UAR memory. The only objects that are allocated from UAR memory
* are the UAR pages which are used for holding Tavor hardware's
* doorbell registers.
*/
/*
* Initialize the resource pool for the UAR pages. Notice
* that the number of UARPGs is configurable. The configured value
* must be less that the maximum value (obtained from the QUERY_DEV_LIM
* command) or the initialization will fail. Note also that by
* specifying the rsrc_start parameter in advance, we direct the
* initialization routine not to attempt to allocated space from the
* Tavor DDR vmem_arena.
*/
PAGESHIFT));
num_prealloc = 0;
if (status != DDI_SUCCESS) {
/* Set "status" and "errormsg" and goto failure */
goto rsrcinitp2_fail;
}
return (DDI_SUCCESS);
return (status);
}
/*
* tavor_rsrc_fini()
*/
void
{
switch (clean) {
/*
* If we add more resources that need to be cleaned up here, we should
* ensure that TAVOR_RSRC_CLEANUP_ALL is still the first entry (i.e.
* corresponds to the last resource allocated).
*/
case TAVOR_RSRC_CLEANUP_ALL:
/* Cleanup the UAR page resource pool */
/* FALLTHROUGH */
/* Cleanup the central MCG handle pointers list */
/* FALLTHROUGH */
/* Cleanup the reference count resource pool */
/* FALLTHROUGH */
/* Cleanup the QP handle resource pool */
/* FALLTHROUGH */
/* Cleanup the address handle resource pool */
/* FALLTHROUGH */
/*
* Cleanup the SRQ handle resource pool.
*
* Note: We only clean up if SRQ is enabled. Otherwise we
* simply fallthrough to the next resource cleanup.
*/
}
/* FALLTHROUGH */
/* Cleanup the CQ handle resource pool */
/* FALLTHROUGH */
/* Cleanup the EQ handle resource pool */
/* FALLTHROUGH */
/* Cleanup the MR handle resource pool */
/* FALLTHROUGH */
/* Cleanup the PD handle resource pool */
/* FALLTHROUGH */
/* Cleanup the EQC table resource pool */
/* FALLTHROUGH */
/* Cleanup the MCG table resource pool */
/* FALLTHROUGH */
/* Cleanup the outstanding command list */
/* FALLTHROUGH */
/* Cleanup the "In" mailbox list */
/* FALLTHROUGH */
/* Cleanup the interrupt "In" mailbox resource pool */
/* FALLTHROUGH */
/* Cleanup the "In" mailbox list */
/* FALLTHROUGH */
/* Cleanup the "In" mailbox resource pool */
/* FALLTHROUGH */
/*
* Cleanup the SRQC table resource pool.
*
* Note: We only clean up if SRQ is enabled. Otherwise we
* simply fallthrough to the next resource cleanup.
*/
}
/* FALLTHROUGH */
/* Cleanup the UAR scratch table resource pool */
/* FALLTHROUGH */
/* Cleanup the UDAV table resource pool */
/* FALLTHROUGH */
/* Cleanup the EQPC table resource pool */
/* FALLTHROUGH */
/* Cleanup the CQC table resource pool */
/* FALLTHROUGH */
/* Cleanup the RDB table resource pool */
/* FALLTHROUGH */
/* Cleanup the QPC table resource pool */
/* FALLTHROUGH */
/* Cleanup the MTT table resource pool */
/* FALLTHROUGH */
/* Cleanup the MPT table resource pool */
/* FALLTHROUGH */
/* Destroy the vmem arena for DDR memory */
break;
/*
* The cleanup below comes from the "Phase 1" initialization step.
* (see tavor_rsrc_init_phase1() above)
*/
/* Cleanup the interrupt "Out" mailbox list */
/* FALLTHROUGH */
/* Cleanup the "Out" mailbox resource pool */
/* FALLTHROUGH */
/* Cleanup the "Out" mailbox list */
/* FALLTHROUGH */
/* Cleanup the "Out" mailbox resource pool */
/* FALLTHROUGH */
/* Free the array of tavor_rsrc_pool_info_t's */
sizeof (tavor_rsrc_pool_info_t));
break;
default:
return;
}
}
/*
* tavor_rsrc_mbox_init()
* Context: Only called from attach() path context
*/
static int
{
/* Allocate and initialize mailbox private structure */
/*
* Initialize many of the default DMA attributes. Then set alignment
* and scatter-gather restrictions specific for mailbox memory.
*/
/* Is object in DDR memory or system memory? */
/* Unable to alloc space for mailboxes */
TAVOR_TNF_ERROR, "");
return (DDI_FAILURE);
}
/* Calculate offset and starting point (in DDR) */
offset);
/* Create new vmem arena for the mailboxes */
/* Unable to create vmem arena */
TAVOR_TNF_ERROR, "");
return (DDI_FAILURE);
}
} else {
}
return (DDI_SUCCESS);
}
/*
* tavor_rsrc_mbox_fini()
*/
static void
{
/* If mailboxes are DDR memory, then destroy and free up vmem */
/* Destroy the specially created mbox vmem arena */
/* Free up the region from the ddr_vmem arena */
}
/* Free up the private struct */
}
/*
* tavor_rsrc_hw_entries_init()
* Context: Only called from attach() path context
*/
static int
{
int status;
/* Make sure number of HW entries makes sense */
if (num_hwentry > max_hwentry) {
return (DDI_FAILURE);
}
/*
* Determine if we need to allocate DDR space to set up the
* "rsrc_start" pointer. Not necessary if "rsrc_start" has already
* been initialized (as is the case for the UAR page init).
*/
/* Make sure HW entries table is aligned as specified */
/* Unable to alloc space for aligned HW table */
TAVOR_TNF_ERROR, "");
return (DDI_FAILURE);
}
/* Calculate offset and starting point (in DDR) */
offset);
} else {
}
/*
* Create new vmem arena for the HW entries table (if rsrc_quantum
* is non-zero). Otherwise if rsrc_quantum is zero, then these HW
* entries are not going to be dynamically allocatable (i.e. they
* won't be allocated/freed through tavor_rsrc_alloc/free). This
* latter option is used for EQPC and UARSCR resource which are, in
* fact, managed by the Tavor hardware.
*/
if (rsrc_pool->rsrc_quantum != 0) {
/* Unable to create vmem arena */
if (rsrc_pool->rsrc_ddr_offset !=
rsrc_pool->rsrc_start) {
}
TAVOR_TNF_ERROR, "");
return (DDI_FAILURE);
}
} else {
}
/* The first HW entries may be reserved by Tavor firmware */
if (num_prealloc != 0) {
if (status != DDI_SUCCESS) {
/* Unable to preallocate the reserved HW entries */
}
if (rsrc_pool->rsrc_ddr_offset !=
rsrc_pool->rsrc_start) {
}
TAVOR_TNF_ERROR, "");
return (DDI_FAILURE);
}
}
return (DDI_SUCCESS);
}
/*
* tavor_rsrc_hw_entries_fini()
*/
static void
{
/* Free up any "reserved" (i.e. preallocated) HW entries */
}
/*
* If we've actually setup a vmem arena for the HW entries, then
* destroy it now
*/
}
/*
* Determine if a region was allocated from the tavor_ddr_vmem
* arena (and free it up if necessary)
*/
}
}
/*
* tavor_rsrc_sw_handles_init()
* Context: Only called from attach() path context
*/
/* ARGSUSED */
static int
{
/* Make sure number of SW handles makes sense */
return (DDI_FAILURE);
}
/*
* Depending on the flags parameter, create a kmem_cache for some
* number of software handle structures. Note: kmem_cache_create()
* will SLEEP until successful.
*/
}
/* Allocate the central list of SW handle pointers */
KM_SLEEP);
}
return (DDI_SUCCESS);
}
/*
* tavor_rsrc_sw_handles_fini()
*/
/* ARGSUSED */
static void
{
/*
* If a "software handle" kmem_cache exists for this resource, then
* destroy it now
*/
}
/* Free up this central list of SW handle pointers */
}
}
/*
* tavor_rsrc_pd_handles_init()
* Context: Only called from attach() path context
*/
static int
{
int status;
/* Initialize the resource pool for software handle table */
if (status != DDI_SUCCESS) {
return (DDI_FAILURE);
}
/* Build vmem arena name from Tavor instance */
/* Create new vmem arena for PD numbers */
/* Unable to create vmem arena */
TAVOR_TNF_ERROR, "");
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
/*
* tavor_rsrc_pd_handles_fini()
*/
static void
{
/* Destroy the specially created UAR scratch table vmem arena */
/* Destroy the "tavor_sw_pd_t" kmem_cache */
}
/*
* tavor_rsrc_mbox_alloc()
* Context: Only called from attach() path context
*/
static int
{
void *addr;
int status;
/* Get the private pointer for the mailboxes */
/*
* Allocate a DMA handle for the mailbox. This will be used for
* two purposes (potentially). First, it could be used below in
* the call to ddi_dma_mem_alloc() - if the mailbox is to come from
* system memory. Second, it is definitely used later to bind
*/
if (status != DDI_SUCCESS) {
return (DDI_FAILURE);
}
/* Is mailbox in DDR memory or system memory? */
/* Use vmem_alloc() to get DDR address of mbox */
VM_SLEEP);
/* No more DDR available for mailbox entries */
TAVOR_TNF_ERROR, "");
return (DDI_FAILURE);
}
/* Calculate kernel virtual address (from the DDR offset) */
} else { /* TAVOR_IN_SYSMEM */
/* Use ddi_dma_mem_alloc() to get memory for mailbox */
if (status != DDI_SUCCESS) {
/* No more sys memory available for mailbox entries */
TAVOR_TNF_ERROR, "");
return (DDI_FAILURE);
}
}
return (DDI_SUCCESS);
}
/*
* tavor_rsrc_mbox_free()
* Context: Can be called from interrupt or base context.
*/
static void
{
void *addr;
/* Is mailbox in DDR memory or system memory? */
/* Calculate the allocated address (the mbox's DDR offset) */
/* Use vmem_free() to free up DDR memory for mailbox */
} else { /* TAVOR_IN_SYSMEM */
/* Use ddi_dma_mem_free() to free up sys memory for mailbox */
}
/* Free the DMA handle for the mailbox */
}
/*
* tavor_rsrc_hw_entry_alloc()
* Context: Can be called from interrupt or base context.
*/
static int
{
void *addr;
int flag;
/*
* Tavor hardware entries (QPC, CQC, EQC, MPT, MTT, etc.) do not
* use dma_handle (because they are in Tavor locally attached DDR
* memory) and, generally, don't use the acc_handle (because the
* entries are not directly accessed by software). The exceptions
* to this rule are the UARPG and UDAV entries.
*/
/*
* Use vmem_xalloc() to get a properly aligned pointer (based on
* the number requested) to the HW entry(ies). This handles the
* cases (for special QPCs and for RDB entries) where we need more
* than one and need to ensure that they are properly aligned.
*/
/* No more HW entries available */
TAVOR_TNF_ERROR, "");
return (DDI_FAILURE);
}
/* If an access handle was provided, fill it in */
if (acc_handle != 0) {
}
/* Calculate vaddr and HW table index (from the DDR offset) */
return (DDI_SUCCESS);
}
/*
* tavor_rsrc_hw_entry_free()
* Context: Can be called from interrupt or base context.
*/
static void
{
void *addr;
/* Calculate the allocated address (the entry's DDR offset) */
/* Use vmem_xfree() to free up the HW table entry */
}
/*
* tavor_rsrc_swhdl_alloc()
* Context: Can be called from interrupt or base context.
*/
static int
{
void *addr;
int flag;
/* Allocate the software handle structure */
"");
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
/*
* tavor_rsrc_swhdl_free()
* Context: Can be called from interrupt or base context.
*/
static void
{
/* Free the software handle structure */
}
/*
* tavor_rsrc_pdhdl_alloc()
* Context: Can be called from interrupt or base context.
*/
static int
{
void *tmpaddr;
/* Allocate the software handle */
if (status != DDI_SUCCESS) {
return (DDI_FAILURE);
}
/* Allocate a PD number for the handle */
/* No more PD number entries available */
TAVOR_TNF_ERROR, "");
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
/*
* tavor_rsrc_pdhdl_free()
* Context: Can be called from interrupt or base context.
*/
static void
{
/* Use vmem_free() to free up the PD number */
/* Free the software handle structure */
}
/*
* tavor_rsrc_pdhdl_constructor()
* Context: Can be called from interrupt or base context.
*/
/* ARGSUSED */
static int
{
return (DDI_SUCCESS);
}
/*
* tavor_rsrc_pdhdl_destructor()
* Context: Can be called from interrupt or base context.
*/
/* ARGSUSED */
static void
{
}
/*
* tavor_rsrc_cqhdl_constructor()
* Context: Can be called from interrupt or base context.
*/
/* ARGSUSED */
static int
{
return (DDI_SUCCESS);
}
/*
* tavor_rsrc_cqhdl_destructor()
* Context: Can be called from interrupt or base context.
*/
/* ARGSUSED */
static void
{
}
/*
* tavor_rsrc_qphdl_constructor()
* Context: Can be called from interrupt or base context.
*/
/* ARGSUSED */
static int
{
return (DDI_SUCCESS);
}
/*
* tavor_rsrc_qphdl_destructor()
* Context: Can be called from interrupt or base context.
*/
/* ARGSUSED */
static void
{
}
/*
* tavor_rsrc_srqhdl_constructor()
* Context: Can be called from interrupt or base context.
*/
/* ARGSUSED */
static int
{
return (DDI_SUCCESS);
}
/*
* tavor_rsrc_srqhdl_destructor()
* Context: Can be called from interrupt or base context.
*/
/* ARGSUSED */
static void
{
}
/*
* tavor_rsrc_refcnt_constructor()
* Context: Can be called from interrupt or base context.
*/
/* ARGSUSED */
static int
{
return (DDI_SUCCESS);
}
/*
* tavor_rsrc_refcnt_destructor()
* Context: Can be called from interrupt or base context.
*/
/* ARGSUSED */
static void
{
}
/*
* tavor_rsrc_ahhdl_constructor()
* Context: Can be called from interrupt or base context.
*/
/* ARGSUSED */
static int
{
return (DDI_SUCCESS);
}
/*
* tavor_rsrc_ahhdl_destructor()
* Context: Can be called from interrupt or base context.
*/
/* ARGSUSED */
static void
{
}
/*
* tavor_rsrc_mrhdl_constructor()
* Context: Can be called from interrupt or base context.
*/
/* ARGSUSED */
static int
{
return (DDI_SUCCESS);
}
/*
* tavor_rsrc_mrhdl_destructor()
* Context: Can be called from interrupt or base context.
*/
/* ARGSUSED */
static void
{
}
/*
* tavor_rsrc_mcg_entry_get_size()
*/
static int
{
/*
* Round the configured number of QP per MCG to next larger
* power-of-2 size and update.
*/
if (ISP2(num_qp_per_mcg)) {
}
/* Now make sure number of QP per MCG makes sense */
if (num_qp_per_mcg > max_qp_per_mcg) {
return (DDI_FAILURE);
}
/* Return the (shift) size of an individual MCG HW entry */
return (DDI_SUCCESS);
}