#include <sys/sysmacros.h>
#include <sys/types.h>
#include <sys/conf.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/modctl.h>
#include <sys/vmem.h>
#include <sys/bitmap.h>
#include <sys/ib/adapters/hermon/hermon.h>
int hermon_rsrc_verbose = 0;
static int hermon_rsrc_mbox_init(hermon_state_t *state,
hermon_rsrc_mbox_info_t *info);
static void hermon_rsrc_mbox_fini(hermon_state_t *state,
hermon_rsrc_mbox_info_t *info);
static int hermon_rsrc_sw_handles_init(hermon_state_t *state,
hermon_rsrc_sw_hdl_info_t *info);
static void hermon_rsrc_sw_handles_fini(hermon_state_t *state,
hermon_rsrc_sw_hdl_info_t *info);
static int hermon_rsrc_pd_handles_init(hermon_state_t *state,
hermon_rsrc_sw_hdl_info_t *info);
static void hermon_rsrc_pd_handles_fini(hermon_state_t *state,
hermon_rsrc_sw_hdl_info_t *info);
static int hermon_rsrc_mbox_alloc(hermon_rsrc_pool_info_t *pool_info,
uint_t num, hermon_rsrc_t *hdl);
static void hermon_rsrc_mbox_free(hermon_rsrc_t *hdl);
static int hermon_rsrc_hw_entry_alloc(hermon_rsrc_pool_info_t *pool_info,
uint_t num, uint_t num_align, uint_t sleepflag, hermon_rsrc_t *hdl);
static void hermon_rsrc_hw_entry_free(hermon_rsrc_pool_info_t *pool_info,
hermon_rsrc_t *hdl);
static int hermon_rsrc_hw_entry_reserve(hermon_rsrc_pool_info_t *pool_info,
uint_t num, uint_t num_align, uint_t sleepflag, hermon_rsrc_t *hdl);
static int hermon_rsrc_hw_entry_icm_confirm(hermon_rsrc_pool_info_t *pool_info,
uint_t num, hermon_rsrc_t *hdl, int num_to_hdl);
static int hermon_rsrc_hw_entry_icm_free(hermon_rsrc_pool_info_t *pool_info,
hermon_rsrc_t *hdl, int num_to_hdl);
static int hermon_rsrc_swhdl_alloc(hermon_rsrc_pool_info_t *pool_info,
uint_t sleepflag, hermon_rsrc_t *hdl);
static void hermon_rsrc_swhdl_free(hermon_rsrc_pool_info_t *pool_info,
hermon_rsrc_t *hdl);
static int hermon_rsrc_pdhdl_alloc(hermon_rsrc_pool_info_t *pool_info,
uint_t sleepflag, hermon_rsrc_t *hdl);
static void hermon_rsrc_pdhdl_free(hermon_rsrc_pool_info_t *pool_info,
hermon_rsrc_t *hdl);
static int hermon_rsrc_fexch_alloc(hermon_state_t *state,
hermon_rsrc_type_t rsrc, uint_t num, uint_t sleepflag, hermon_rsrc_t *hdl);
static void hermon_rsrc_fexch_free(hermon_state_t *state, hermon_rsrc_t *hdl);
static int hermon_rsrc_rfci_alloc(hermon_state_t *state,
hermon_rsrc_type_t rsrc, uint_t num, uint_t sleepflag, hermon_rsrc_t *hdl);
static void hermon_rsrc_rfci_free(hermon_state_t *state, hermon_rsrc_t *hdl);
static int hermon_rsrc_pdhdl_constructor(void *pd, void *priv, int flags);
static void hermon_rsrc_pdhdl_destructor(void *pd, void *state);
static int hermon_rsrc_cqhdl_constructor(void *cq, void *priv, int flags);
static void hermon_rsrc_cqhdl_destructor(void *cq, void *state);
static int hermon_rsrc_qphdl_constructor(void *cq, void *priv, int flags);
static void hermon_rsrc_qphdl_destructor(void *cq, void *state);
static int hermon_rsrc_srqhdl_constructor(void *srq, void *priv, int flags);
static void hermon_rsrc_srqhdl_destructor(void *srq, void *state);
static int hermon_rsrc_refcnt_constructor(void *rc, void *priv, int flags);
static void hermon_rsrc_refcnt_destructor(void *rc, void *state);
static int hermon_rsrc_ahhdl_constructor(void *ah, void *priv, int flags);
static void hermon_rsrc_ahhdl_destructor(void *ah, void *state);
static int hermon_rsrc_mrhdl_constructor(void *mr, void *priv, int flags);
static void hermon_rsrc_mrhdl_destructor(void *mr, void *state);
static int hermon_rsrc_mcg_entry_get_size(hermon_state_t *state,
uint_t *mcg_size_shift);
int
hermon_rsrc_alloc(hermon_state_t *state, hermon_rsrc_type_t rsrc, uint_t num,
uint_t sleepflag, hermon_rsrc_t **hdl)
{
hermon_rsrc_pool_info_t *rsrc_pool;
hermon_rsrc_t *tmp_rsrc_hdl;
int flag, status = DDI_FAILURE;
ASSERT(state != NULL);
ASSERT(hdl != NULL);
rsrc_pool = &state->hs_rsrc_hdl[rsrc];
ASSERT(rsrc_pool != NULL);
flag = (sleepflag == HERMON_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
tmp_rsrc_hdl = kmem_cache_alloc(state->hs_rsrc_cache, flag);
if (tmp_rsrc_hdl == NULL) {
return (DDI_FAILURE);
}
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tmp_rsrc_hdl))
tmp_rsrc_hdl->rsrc_type = rsrc;
switch (rsrc) {
case HERMON_IN_MBOX:
case HERMON_OUT_MBOX:
case HERMON_INTR_IN_MBOX:
case HERMON_INTR_OUT_MBOX:
status = hermon_rsrc_mbox_alloc(rsrc_pool, num, tmp_rsrc_hdl);
break;
case HERMON_DMPT:
case HERMON_QPC:
status = hermon_rsrc_hw_entry_alloc(rsrc_pool, num, num,
sleepflag, tmp_rsrc_hdl);
break;
case HERMON_QPC_FEXCH_PORT1:
case HERMON_QPC_FEXCH_PORT2:
status = hermon_rsrc_fexch_alloc(state, rsrc, num,
sleepflag, tmp_rsrc_hdl);
break;
case HERMON_QPC_RFCI_PORT1:
case HERMON_QPC_RFCI_PORT2:
status = hermon_rsrc_rfci_alloc(state, rsrc, num,
sleepflag, tmp_rsrc_hdl);
break;
case HERMON_MTT:
case HERMON_CQC:
case HERMON_SRQC:
case HERMON_EQC:
case HERMON_MCG:
case HERMON_UARPG:
status = hermon_rsrc_hw_entry_alloc(rsrc_pool, num, 1,
sleepflag, tmp_rsrc_hdl);
break;
case HERMON_MRHDL:
case HERMON_EQHDL:
case HERMON_CQHDL:
case HERMON_SRQHDL:
case HERMON_AHHDL:
case HERMON_QPHDL:
case HERMON_REFCNT:
status = hermon_rsrc_swhdl_alloc(rsrc_pool, sleepflag,
tmp_rsrc_hdl);
break;
case HERMON_PDHDL:
status = hermon_rsrc_pdhdl_alloc(rsrc_pool, sleepflag,
tmp_rsrc_hdl);
break;
case HERMON_RDB:
case HERMON_ALTC:
case HERMON_AUXC:
case HERMON_CMPT_QPC:
case HERMON_CMPT_SRQC:
case HERMON_CMPT_CQC:
case HERMON_CMPT_EQC:
default:
HERMON_WARNING(state, "unexpected resource type in alloc ");
cmn_err(CE_WARN, "Resource type %x \n", rsrc_pool->rsrc_type);
break;
}
if (status != DDI_SUCCESS) {
kmem_cache_free(state->hs_rsrc_cache, tmp_rsrc_hdl);
return (DDI_FAILURE);
} else {
*hdl = tmp_rsrc_hdl;
return (DDI_SUCCESS);
}
}
int
hermon_rsrc_reserve(hermon_state_t *state, hermon_rsrc_type_t rsrc, uint_t num,
uint_t sleepflag, hermon_rsrc_t **hdl)
{
hermon_rsrc_pool_info_t *rsrc_pool;
hermon_rsrc_t *tmp_rsrc_hdl;
int flag, status = DDI_FAILURE;
ASSERT(state != NULL);
ASSERT(hdl != NULL);
rsrc_pool = &state->hs_rsrc_hdl[rsrc];
ASSERT(rsrc_pool != NULL);
flag = (sleepflag == HERMON_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
tmp_rsrc_hdl = kmem_cache_alloc(state->hs_rsrc_cache, flag);
if (tmp_rsrc_hdl == NULL) {
return (DDI_FAILURE);
}
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tmp_rsrc_hdl))
tmp_rsrc_hdl->rsrc_type = rsrc;
switch (rsrc) {
case HERMON_QPC:
case HERMON_DMPT:
case HERMON_MTT:
status = hermon_rsrc_hw_entry_reserve(rsrc_pool, num, num,
sleepflag, tmp_rsrc_hdl);
break;
default:
HERMON_WARNING(state, "unexpected resource type in reserve ");
cmn_err(CE_WARN, "Resource type %x \n", rsrc);
break;
}
if (status != DDI_SUCCESS) {
kmem_cache_free(state->hs_rsrc_cache, tmp_rsrc_hdl);
return (DDI_FAILURE);
} else {
*hdl = tmp_rsrc_hdl;
return (DDI_SUCCESS);
}
}
static int
hermon_rsrc_fexch_alloc(hermon_state_t *state, hermon_rsrc_type_t rsrc,
uint_t num, uint_t sleepflag, hermon_rsrc_t *hdl)
{
hermon_fcoib_t *fcoib;
void *addr;
uint32_t fexch_qpn_base;
hermon_rsrc_pool_info_t *qpc_pool, *mpt_pool, *mtt_pool;
int flag, status;
hermon_rsrc_t mpt_hdl;
hermon_rsrc_t mtt_hdl;
uint_t portm1;
uint_t nummtt;
vmem_t *vmp;
ASSERT(state != NULL);
ASSERT(hdl != NULL);
if ((state->hs_ibtfinfo.hca_attr->hca_flags2 & IBT_HCA2_FC) == 0)
return (DDI_FAILURE);
portm1 = rsrc - HERMON_QPC_FEXCH_PORT1;
fcoib = &state->hs_fcoib;
flag = (sleepflag == HERMON_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
vmp = fcoib->hfc_fexch_vmemp[portm1];
addr = vmem_xalloc(vmp, num, num, 0, 0, NULL, NULL, flag | VM_FIRSTFIT);
if (addr == NULL) {
return (DDI_FAILURE);
}
fexch_qpn_base = (uint32_t)((uintptr_t)addr -
fcoib->hfc_vmemstart + fcoib->hfc_fexch_base[portm1]);
qpc_pool = &state->hs_rsrc_hdl[HERMON_QPC];
hdl->hr_len = num << qpc_pool->rsrc_shift;
hdl->hr_addr = addr;
hdl->hr_indx = fexch_qpn_base;
status = hermon_rsrc_hw_entry_icm_confirm(qpc_pool, num, hdl, 1);
if (status != DDI_SUCCESS) {
vmem_xfree(vmp, addr, num);
return (DDI_FAILURE);
}
mpt_pool = &state->hs_rsrc_hdl[HERMON_DMPT];
mpt_hdl.hr_len = num << mpt_pool->rsrc_shift;
mpt_hdl.hr_addr = NULL;
mpt_hdl.hr_indx = fcoib->hfc_mpt_base[portm1] +
(fexch_qpn_base - fcoib->hfc_fexch_base[portm1]);
status = hermon_rsrc_hw_entry_icm_confirm(mpt_pool, num, &mpt_hdl, 0);
if (status != DDI_SUCCESS) {
status = hermon_rsrc_hw_entry_icm_free(qpc_pool, hdl, 1);
vmem_xfree(vmp, addr, num);
return (DDI_FAILURE);
}
nummtt = fcoib->hfc_mtts_per_mpt;
num *= nummtt;
mtt_pool = &state->hs_rsrc_hdl[HERMON_MTT];
mtt_hdl.hr_len = num << mtt_pool->rsrc_shift;
mtt_hdl.hr_addr = NULL;
mtt_hdl.hr_indx = fcoib->hfc_mtt_base[portm1] +
(fexch_qpn_base - fcoib->hfc_fexch_base[portm1]) *
nummtt;
status = hermon_rsrc_hw_entry_icm_confirm(mtt_pool, num, &mtt_hdl, 0);
if (status != DDI_SUCCESS) {
vmem_xfree(vmp, addr, num);
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static void
hermon_rsrc_fexch_free(hermon_state_t *state, hermon_rsrc_t *hdl)
{
hermon_fcoib_t *fcoib;
uint_t portm1;
ASSERT(state != NULL);
ASSERT(hdl != NULL);
portm1 = hdl->rsrc_type - HERMON_QPC_FEXCH_PORT1;
fcoib = &state->hs_fcoib;
vmem_xfree(fcoib->hfc_fexch_vmemp[portm1], hdl->hr_addr,
hdl->hr_len >> state->hs_rsrc_hdl[HERMON_QPC].rsrc_shift);
}
static int
hermon_rsrc_rfci_alloc(hermon_state_t *state, hermon_rsrc_type_t rsrc,
uint_t num, uint_t sleepflag, hermon_rsrc_t *hdl)
{
hermon_fcoib_t *fcoib;
void *addr;
uint32_t rfci_qpn_base;
hermon_rsrc_pool_info_t *qpc_pool;
int flag, status;
uint_t portm1;
vmem_t *vmp;
ASSERT(state != NULL);
ASSERT(hdl != NULL);
if ((state->hs_ibtfinfo.hca_attr->hca_flags2 & IBT_HCA2_FC) == 0)
return (DDI_FAILURE);
portm1 = rsrc - HERMON_QPC_RFCI_PORT1;
fcoib = &state->hs_fcoib;
flag = (sleepflag == HERMON_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
vmp = fcoib->hfc_rfci_vmemp[portm1];
addr = vmem_xalloc(vmp, num, num, 0, 0, NULL, NULL, flag | VM_FIRSTFIT);
if (addr == NULL) {
return (DDI_FAILURE);
}
rfci_qpn_base = (uint32_t)((uintptr_t)addr -
fcoib->hfc_vmemstart + fcoib->hfc_rfci_base[portm1]);
qpc_pool = &state->hs_rsrc_hdl[HERMON_QPC];
hdl->hr_len = num << qpc_pool->rsrc_shift;
hdl->hr_addr = addr;
hdl->hr_indx = rfci_qpn_base;
status = hermon_rsrc_hw_entry_icm_confirm(qpc_pool, num, hdl, 1);
if (status != DDI_SUCCESS) {
vmem_xfree(vmp, addr, num);
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static void
hermon_rsrc_rfci_free(hermon_state_t *state, hermon_rsrc_t *hdl)
{
hermon_fcoib_t *fcoib;
uint_t portm1;
ASSERT(state != NULL);
ASSERT(hdl != NULL);
portm1 = hdl->rsrc_type - HERMON_QPC_RFCI_PORT1;
fcoib = &state->hs_fcoib;
vmem_xfree(fcoib->hfc_rfci_vmemp[portm1], hdl->hr_addr,
hdl->hr_len >> state->hs_rsrc_hdl[HERMON_QPC].rsrc_shift);
}
void
hermon_rsrc_free(hermon_state_t *state, hermon_rsrc_t **hdl)
{
hermon_rsrc_pool_info_t *rsrc_pool;
ASSERT(state != NULL);
ASSERT(hdl != NULL);
rsrc_pool = &state->hs_rsrc_hdl[(*hdl)->rsrc_type];
ASSERT(rsrc_pool != NULL);
switch (rsrc_pool->rsrc_type) {
case HERMON_IN_MBOX:
case HERMON_OUT_MBOX:
case HERMON_INTR_IN_MBOX:
case HERMON_INTR_OUT_MBOX:
hermon_rsrc_mbox_free(*hdl);
break;
case HERMON_QPC_FEXCH_PORT1:
case HERMON_QPC_FEXCH_PORT2:
hermon_rsrc_fexch_free(state, *hdl);
break;
case HERMON_QPC_RFCI_PORT1:
case HERMON_QPC_RFCI_PORT2:
hermon_rsrc_rfci_free(state, *hdl);
break;
case HERMON_QPC:
case HERMON_CQC:
case HERMON_SRQC:
case HERMON_EQC:
case HERMON_DMPT:
case HERMON_MCG:
case HERMON_MTT:
case HERMON_UARPG:
hermon_rsrc_hw_entry_free(rsrc_pool, *hdl);
break;
case HERMON_MRHDL:
case HERMON_EQHDL:
case HERMON_CQHDL:
case HERMON_SRQHDL:
case HERMON_AHHDL:
case HERMON_QPHDL:
case HERMON_REFCNT:
hermon_rsrc_swhdl_free(rsrc_pool, *hdl);
break;
case HERMON_PDHDL:
hermon_rsrc_pdhdl_free(rsrc_pool, *hdl);
break;
case HERMON_RDB:
case HERMON_ALTC:
case HERMON_AUXC:
case HERMON_CMPT_QPC:
case HERMON_CMPT_SRQC:
case HERMON_CMPT_CQC:
case HERMON_CMPT_EQC:
default:
cmn_err(CE_CONT, "!rsrc_type = 0x%x\n", rsrc_pool->rsrc_type);
break;
}
kmem_cache_free(state->hs_rsrc_cache, *hdl);
*hdl = NULL;
}
int
hermon_rsrc_init_phase1(hermon_state_t *state)
{
hermon_rsrc_pool_info_t *rsrc_pool;
hermon_rsrc_mbox_info_t mbox_info;
hermon_rsrc_cleanup_level_t cleanup;
hermon_cfg_profile_t *cfgprof;
uint64_t num, size;
int status;
char *rsrc_name;
ASSERT(state != NULL);
cleanup = HERMON_RSRC_CLEANUP_LEVEL0;
rsrc_name = kmem_zalloc(HERMON_RSRC_NAME_MAXLEN, KM_SLEEP);
HERMON_RSRC_NAME(rsrc_name, HERMON_RSRC_CACHE);
state->hs_rsrc_cache = kmem_cache_create(rsrc_name,
sizeof (hermon_rsrc_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
state->hs_rsrc_hdl = kmem_zalloc(HERMON_NUM_RESOURCES *
sizeof (hermon_rsrc_pool_info_t), KM_SLEEP);
cfgprof = state->hs_cfg_profile;
num = ((uint64_t)1 << cfgprof->cp_log_num_outmbox);
size = ((uint64_t)1 << cfgprof->cp_log_outmbox_size);
rsrc_pool = &state->hs_rsrc_hdl[HERMON_OUT_MBOX];
rsrc_pool->rsrc_loc = HERMON_IN_SYSMEM;
rsrc_pool->rsrc_pool_size = (size * num);
rsrc_pool->rsrc_shift = cfgprof->cp_log_outmbox_size;
rsrc_pool->rsrc_quantum = (uint_t)size;
rsrc_pool->rsrc_align = HERMON_MBOX_ALIGN;
rsrc_pool->rsrc_state = state;
mbox_info.mbi_num = num;
mbox_info.mbi_size = size;
mbox_info.mbi_rsrcpool = rsrc_pool;
status = hermon_rsrc_mbox_init(state, &mbox_info);
if (status != DDI_SUCCESS) {
hermon_rsrc_fini(state, cleanup);
status = DDI_FAILURE;
goto rsrcinitp1_fail;
}
cleanup = HERMON_RSRC_CLEANUP_LEVEL1;
status = hermon_outmbox_list_init(state);
if (status != DDI_SUCCESS) {
hermon_rsrc_fini(state, cleanup);
status = DDI_FAILURE;
goto rsrcinitp1_fail;
}
cleanup = HERMON_RSRC_CLEANUP_LEVEL2;
num = ((uint64_t)1 << cfgprof->cp_log_num_intr_outmbox);
size = ((uint64_t)1 << cfgprof->cp_log_outmbox_size);
rsrc_pool = &state->hs_rsrc_hdl[HERMON_INTR_OUT_MBOX];
rsrc_pool->rsrc_loc = HERMON_IN_SYSMEM;
rsrc_pool->rsrc_pool_size = (size * num);
rsrc_pool->rsrc_shift = cfgprof->cp_log_outmbox_size;
rsrc_pool->rsrc_quantum = (uint_t)size;
rsrc_pool->rsrc_align = HERMON_MBOX_ALIGN;
rsrc_pool->rsrc_state = state;
mbox_info.mbi_num = num;
mbox_info.mbi_size = size;
mbox_info.mbi_rsrcpool = rsrc_pool;
status = hermon_rsrc_mbox_init(state, &mbox_info);
if (status != DDI_SUCCESS) {
hermon_rsrc_fini(state, cleanup);
status = DDI_FAILURE;
goto rsrcinitp1_fail;
}
cleanup = HERMON_RSRC_CLEANUP_LEVEL3;
status = hermon_intr_outmbox_list_init(state);
if (status != DDI_SUCCESS) {
hermon_rsrc_fini(state, cleanup);
status = DDI_FAILURE;
goto rsrcinitp1_fail;
}
cleanup = HERMON_RSRC_CLEANUP_LEVEL4;
num = ((uint64_t)1 << cfgprof->cp_log_num_inmbox);
size = ((uint64_t)1 << cfgprof->cp_log_inmbox_size);
rsrc_pool = &state->hs_rsrc_hdl[HERMON_IN_MBOX];
rsrc_pool->rsrc_loc = HERMON_IN_SYSMEM;
rsrc_pool->rsrc_pool_size = (size * num);
rsrc_pool->rsrc_shift = cfgprof->cp_log_inmbox_size;
rsrc_pool->rsrc_quantum = (uint_t)size;
rsrc_pool->rsrc_align = HERMON_MBOX_ALIGN;
rsrc_pool->rsrc_state = state;
mbox_info.mbi_num = num;
mbox_info.mbi_size = size;
mbox_info.mbi_rsrcpool = rsrc_pool;
status = hermon_rsrc_mbox_init(state, &mbox_info);
if (status != DDI_SUCCESS) {
hermon_rsrc_fini(state, cleanup);
status = DDI_FAILURE;
goto rsrcinitp1_fail;
}
cleanup = HERMON_RSRC_CLEANUP_LEVEL5;
status = hermon_inmbox_list_init(state);
if (status != DDI_SUCCESS) {
hermon_rsrc_fini(state, cleanup);
status = DDI_FAILURE;
goto rsrcinitp1_fail;
}
cleanup = HERMON_RSRC_CLEANUP_LEVEL6;
num = ((uint64_t)1 << cfgprof->cp_log_num_intr_inmbox);
size = ((uint64_t)1 << cfgprof->cp_log_inmbox_size);
rsrc_pool = &state->hs_rsrc_hdl[HERMON_INTR_IN_MBOX];
rsrc_pool->rsrc_loc = HERMON_IN_SYSMEM;
rsrc_pool->rsrc_pool_size = (size * num);
rsrc_pool->rsrc_shift = cfgprof->cp_log_inmbox_size;
rsrc_pool->rsrc_quantum = (uint_t)size;
rsrc_pool->rsrc_align = HERMON_MBOX_ALIGN;
rsrc_pool->rsrc_state = state;
mbox_info.mbi_num = num;
mbox_info.mbi_size = size;
mbox_info.mbi_rsrcpool = rsrc_pool;
status = hermon_rsrc_mbox_init(state, &mbox_info);
if (status != DDI_SUCCESS) {
hermon_rsrc_fini(state, cleanup);
status = DDI_FAILURE;
goto rsrcinitp1_fail;
}
cleanup = HERMON_RSRC_CLEANUP_LEVEL7;
status = hermon_intr_inmbox_list_init(state);
if (status != DDI_SUCCESS) {
hermon_rsrc_fini(state, cleanup);
status = DDI_FAILURE;
goto rsrcinitp1_fail;
}
cleanup = HERMON_RSRC_CLEANUP_PHASE1_COMPLETE;
kmem_free(rsrc_name, HERMON_RSRC_NAME_MAXLEN);
return (DDI_SUCCESS);
rsrcinitp1_fail:
kmem_free(rsrc_name, HERMON_RSRC_NAME_MAXLEN);
return (status);
}
int
hermon_rsrc_init_phase2(hermon_state_t *state)
{
hermon_rsrc_sw_hdl_info_t hdl_info;
hermon_rsrc_hw_entry_info_t entry_info;
hermon_rsrc_pool_info_t *rsrc_pool;
hermon_rsrc_cleanup_level_t cleanup, ncleanup;
hermon_cfg_profile_t *cfgprof;
hermon_hw_querydevlim_t *devlim;
uint64_t num, max, num_prealloc;
uint_t mcg_size, mcg_size_shift;
int i, status;
char *rsrc_name;
ASSERT(state != NULL);
cleanup = HERMON_RSRC_CLEANUP_PHASE1_COMPLETE;
rsrc_name = kmem_zalloc(HERMON_RSRC_NAME_MAXLEN, KM_SLEEP);
cfgprof = state->hs_cfg_profile;
devlim = &state->hs_devlim;
for (i = 0; i < HERMON_NUM_ICM_RESOURCES; i++) {
rsrc_pool = &state->hs_rsrc_hdl[i];
rsrc_pool->rsrc_type = i;
rsrc_pool->rsrc_state = state;
switch (i) {
case HERMON_MTT:
max = ((uint64_t)1 << devlim->log_max_mtt);
num_prealloc = ((uint64_t)1 << devlim->log_rsvd_mtt);
HERMON_RSRC_NAME(rsrc_name, HERMON_MTT_VMEM);
ncleanup = HERMON_RSRC_CLEANUP_LEVEL9;
break;
case HERMON_DMPT:
max = ((uint64_t)1 << devlim->log_max_dmpt);
num_prealloc = ((uint64_t)1 << devlim->log_rsvd_dmpt);
HERMON_RSRC_NAME(rsrc_name, HERMON_DMPT_VMEM);
ncleanup = HERMON_RSRC_CLEANUP_LEVEL10;
break;
case HERMON_QPC:
max = ((uint64_t)1 << devlim->log_max_qp);
num_prealloc = ((uint64_t)1 << devlim->log_rsvd_qp);
HERMON_RSRC_NAME(rsrc_name, HERMON_QPC_VMEM);
ncleanup = HERMON_RSRC_CLEANUP_LEVEL11;
break;
case HERMON_CQC:
max = ((uint64_t)1 << devlim->log_max_cq);
num_prealloc = ((uint64_t)1 << devlim->log_rsvd_cq);
HERMON_RSRC_NAME(rsrc_name, HERMON_CQC_VMEM);
ncleanup = HERMON_RSRC_CLEANUP_LEVEL13;
break;
case HERMON_SRQC:
max = ((uint64_t)1 << devlim->log_max_srq);
num_prealloc = ((uint64_t)1 << devlim->log_rsvd_srq);
HERMON_RSRC_NAME(rsrc_name, HERMON_SRQC_VMEM);
ncleanup = HERMON_RSRC_CLEANUP_LEVEL16;
break;
case HERMON_EQC:
max = ((uint64_t)1 << devlim->log_max_eq);
num_prealloc = state->hs_rsvd_eqs;
HERMON_RSRC_NAME(rsrc_name, HERMON_EQC_VMEM);
ncleanup = HERMON_RSRC_CLEANUP_LEVEL18;
break;
case HERMON_MCG:
case HERMON_AUXC:
case HERMON_ALTC:
case HERMON_RDB:
case HERMON_CMPT_QPC:
case HERMON_CMPT_SRQC:
case HERMON_CMPT_CQC:
case HERMON_CMPT_EQC:
default:
continue;
}
rsrc_pool->rsrc_state = state;
rsrc_pool->rsrc_loc = HERMON_IN_ICM;
rsrc_pool->rsrc_pool_size = state->hs_icm[i].table_size;
rsrc_pool->rsrc_align = state->hs_icm[i].table_size;
rsrc_pool->rsrc_shift = state->hs_icm[i].log_object_size;
rsrc_pool->rsrc_quantum = state->hs_icm[i].object_size;
entry_info.hwi_num = state->hs_icm[i].num_entries;
entry_info.hwi_max = max;
entry_info.hwi_prealloc = num_prealloc;
entry_info.hwi_rsrcpool = rsrc_pool;
entry_info.hwi_rsrcname = rsrc_name;
status = hermon_rsrc_hw_entries_init(state, &entry_info);
if (status != DDI_SUCCESS) {
hermon_rsrc_fini(state, cleanup);
status = DDI_FAILURE;
goto rsrcinitp2_fail;
}
cleanup = ncleanup;
}
status = hermon_rsrc_mcg_entry_get_size(state, &mcg_size_shift);
if (status != DDI_SUCCESS) {
hermon_rsrc_fini(state, cleanup);
status = DDI_FAILURE;
goto rsrcinitp2_fail;
}
mcg_size = HERMON_MCGMEM_SZ(state);
num = ((uint64_t)1 << cfgprof->cp_log_num_mcg);
max = ((uint64_t)1 << devlim->log_max_mcg);
num_prealloc = ((uint64_t)1 << cfgprof->cp_log_num_mcg_hash);
rsrc_pool = &state->hs_rsrc_hdl[HERMON_MCG];
rsrc_pool->rsrc_loc = HERMON_IN_ICM;
rsrc_pool->rsrc_pool_size = (mcg_size * num);
rsrc_pool->rsrc_shift = mcg_size_shift;
rsrc_pool->rsrc_quantum = mcg_size;
rsrc_pool->rsrc_align = (mcg_size * num);
rsrc_pool->rsrc_state = state;
HERMON_RSRC_NAME(rsrc_name, HERMON_MCG_VMEM);
entry_info.hwi_num = num;
entry_info.hwi_max = max;
entry_info.hwi_prealloc = num_prealloc;
entry_info.hwi_rsrcpool = rsrc_pool;
entry_info.hwi_rsrcname = rsrc_name;
status = hermon_rsrc_hw_entries_init(state, &entry_info);
if (status != DDI_SUCCESS) {
hermon_rsrc_fini(state, cleanup);
status = DDI_FAILURE;
goto rsrcinitp2_fail;
}
cleanup = HERMON_RSRC_CLEANUP_LEVEL19;
status = hermon_outstanding_cmdlist_init(state);
if (status != DDI_SUCCESS) {
hermon_rsrc_fini(state, cleanup);
status = DDI_FAILURE;
goto rsrcinitp2_fail;
}
cleanup = HERMON_RSRC_CLEANUP_LEVEL20;
rsrc_pool = &state->hs_rsrc_hdl[HERMON_PDHDL];
rsrc_pool->rsrc_loc = HERMON_IN_SYSMEM;
rsrc_pool->rsrc_quantum = sizeof (struct hermon_sw_pd_s);
rsrc_pool->rsrc_state = state;
HERMON_RSRC_NAME(rsrc_name, HERMON_PDHDL_CACHE);
hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_pd);
hdl_info.swi_max = ((uint64_t)1 << devlim->log_max_pd);
hdl_info.swi_rsrcpool = rsrc_pool;
hdl_info.swi_constructor = hermon_rsrc_pdhdl_constructor;
hdl_info.swi_destructor = hermon_rsrc_pdhdl_destructor;
hdl_info.swi_rsrcname = rsrc_name;
hdl_info.swi_flags = HERMON_SWHDL_KMEMCACHE_INIT;
status = hermon_rsrc_pd_handles_init(state, &hdl_info);
if (status != DDI_SUCCESS) {
hermon_rsrc_fini(state, cleanup);
status = DDI_FAILURE;
goto rsrcinitp2_fail;
}
cleanup = HERMON_RSRC_CLEANUP_LEVEL21;
for (i = HERMON_NUM_ICM_RESOURCES; i < HERMON_NUM_RESOURCES; i++) {
rsrc_pool = &state->hs_rsrc_hdl[i];
rsrc_pool->rsrc_type = i;
switch (i) {
case HERMON_MRHDL:
rsrc_pool->rsrc_quantum =
sizeof (struct hermon_sw_mr_s);
HERMON_RSRC_NAME(rsrc_name, HERMON_MRHDL_CACHE);
hdl_info.swi_num =
((uint64_t)1 << cfgprof->cp_log_num_dmpt) +
((uint64_t)1 << cfgprof->cp_log_num_cmpt);
hdl_info.swi_max =
((uint64_t)1 << cfgprof->cp_log_num_dmpt) +
((uint64_t)1 << cfgprof->cp_log_num_cmpt);
hdl_info.swi_constructor =
hermon_rsrc_mrhdl_constructor;
hdl_info.swi_destructor = hermon_rsrc_mrhdl_destructor;
hdl_info.swi_flags = HERMON_SWHDL_KMEMCACHE_INIT;
ncleanup = HERMON_RSRC_CLEANUP_LEVEL22;
break;
case HERMON_EQHDL:
rsrc_pool->rsrc_quantum =
sizeof (struct hermon_sw_eq_s);
HERMON_RSRC_NAME(rsrc_name, HERMON_EQHDL_CACHE);
hdl_info.swi_num = HERMON_NUM_EQ;
hdl_info.swi_max = ((uint64_t)1 << devlim->log_max_eq);
hdl_info.swi_constructor = NULL;
hdl_info.swi_destructor = NULL;
hdl_info.swi_flags = HERMON_SWHDL_KMEMCACHE_INIT;
ncleanup = HERMON_RSRC_CLEANUP_LEVEL23;
break;
case HERMON_CQHDL:
rsrc_pool->rsrc_quantum =
sizeof (struct hermon_sw_cq_s);
HERMON_RSRC_NAME(rsrc_name, HERMON_CQHDL_CACHE);
hdl_info.swi_num =
(uint64_t)1 << cfgprof->cp_log_num_cq;
hdl_info.swi_max = (uint64_t)1 << devlim->log_max_cq;
hdl_info.swi_constructor =
hermon_rsrc_cqhdl_constructor;
hdl_info.swi_destructor = hermon_rsrc_cqhdl_destructor;
hdl_info.swi_flags = HERMON_SWHDL_KMEMCACHE_INIT;
hdl_info.swi_prealloc_sz = sizeof (hermon_cqhdl_t);
ncleanup = HERMON_RSRC_CLEANUP_LEVEL24;
break;
case HERMON_SRQHDL:
rsrc_pool->rsrc_quantum =
sizeof (struct hermon_sw_srq_s);
HERMON_RSRC_NAME(rsrc_name, HERMON_SRQHDL_CACHE);
hdl_info.swi_num =
(uint64_t)1 << cfgprof->cp_log_num_srq;
hdl_info.swi_max = (uint64_t)1 << devlim->log_max_srq;
hdl_info.swi_constructor =
hermon_rsrc_srqhdl_constructor;
hdl_info.swi_destructor = hermon_rsrc_srqhdl_destructor;
hdl_info.swi_flags = HERMON_SWHDL_KMEMCACHE_INIT;
hdl_info.swi_prealloc_sz = sizeof (hermon_srqhdl_t);
ncleanup = HERMON_RSRC_CLEANUP_LEVEL25;
break;
case HERMON_AHHDL:
rsrc_pool->rsrc_quantum =
sizeof (struct hermon_sw_ah_s);
HERMON_RSRC_NAME(rsrc_name, HERMON_AHHDL_CACHE);
hdl_info.swi_num =
(uint64_t)1 << cfgprof->cp_log_num_ah;
hdl_info.swi_max = HERMON_NUM_AH;
hdl_info.swi_constructor =
hermon_rsrc_ahhdl_constructor;
hdl_info.swi_destructor = hermon_rsrc_ahhdl_destructor;
hdl_info.swi_flags = HERMON_SWHDL_KMEMCACHE_INIT;
ncleanup = HERMON_RSRC_CLEANUP_LEVEL26;
break;
case HERMON_QPHDL:
rsrc_pool->rsrc_quantum =
sizeof (struct hermon_sw_qp_s);
HERMON_RSRC_NAME(rsrc_name, HERMON_QPHDL_CACHE);
hdl_info.swi_num =
(uint64_t)1 << cfgprof->cp_log_num_qp;
hdl_info.swi_max = (uint64_t)1 << devlim->log_max_qp;
hdl_info.swi_constructor =
hermon_rsrc_qphdl_constructor;
hdl_info.swi_destructor = hermon_rsrc_qphdl_destructor;
hdl_info.swi_flags = HERMON_SWHDL_KMEMCACHE_INIT;
hdl_info.swi_prealloc_sz = sizeof (hermon_qphdl_t);
ncleanup = HERMON_RSRC_CLEANUP_LEVEL27;
break;
case HERMON_REFCNT:
rsrc_pool->rsrc_quantum = sizeof (hermon_sw_refcnt_t);
HERMON_RSRC_NAME(rsrc_name, HERMON_REFCNT_CACHE);
hdl_info.swi_num =
(uint64_t)1 << cfgprof->cp_log_num_dmpt;
hdl_info.swi_max = (uint64_t)1 << devlim->log_max_dmpt;
hdl_info.swi_constructor =
hermon_rsrc_refcnt_constructor;
hdl_info.swi_destructor = hermon_rsrc_refcnt_destructor;
hdl_info.swi_flags = HERMON_SWHDL_KMEMCACHE_INIT;
ncleanup = HERMON_RSRC_CLEANUP_LEVEL28;
break;
default:
continue;
}
rsrc_pool->rsrc_loc = HERMON_IN_SYSMEM;
rsrc_pool->rsrc_state = state;
hdl_info.swi_rsrcpool = rsrc_pool;
hdl_info.swi_rsrcname = rsrc_name;
status = hermon_rsrc_sw_handles_init(state, &hdl_info);
if (status != DDI_SUCCESS) {
hermon_rsrc_fini(state, cleanup);
status = DDI_FAILURE;
goto rsrcinitp2_fail;
}
cleanup = ncleanup;
}
hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_mcg);
hdl_info.swi_max = ((uint64_t)1 << devlim->log_max_mcg);
hdl_info.swi_flags = HERMON_SWHDL_TABLE_INIT;
hdl_info.swi_prealloc_sz = sizeof (struct hermon_sw_mcg_list_s);
status = hermon_rsrc_sw_handles_init(state, &hdl_info);
if (status != DDI_SUCCESS) {
hermon_rsrc_fini(state, cleanup);
status = DDI_FAILURE;
goto rsrcinitp2_fail;
}
state->hs_mcghdl = hdl_info.swi_table_ptr;
cleanup = HERMON_RSRC_CLEANUP_LEVEL29;
num = ((uint64_t)1 << cfgprof->cp_log_num_uar);
max = num;
num_prealloc = max(devlim->num_rsvd_uar, 128);
rsrc_pool = &state->hs_rsrc_hdl[HERMON_UARPG];
rsrc_pool->rsrc_loc = HERMON_IN_UAR;
rsrc_pool->rsrc_pool_size = (num << PAGESHIFT);
rsrc_pool->rsrc_shift = PAGESHIFT;
rsrc_pool->rsrc_quantum = (uint_t)PAGESIZE;
rsrc_pool->rsrc_align = PAGESIZE;
rsrc_pool->rsrc_state = state;
rsrc_pool->rsrc_start = (void *)state->hs_reg_uar_baseaddr;
HERMON_RSRC_NAME(rsrc_name, HERMON_UAR_PAGE_VMEM_ATTCH);
entry_info.hwi_num = num;
entry_info.hwi_max = max;
entry_info.hwi_prealloc = num_prealloc;
entry_info.hwi_rsrcpool = rsrc_pool;
entry_info.hwi_rsrcname = rsrc_name;
status = hermon_rsrc_hw_entries_init(state, &entry_info);
if (status != DDI_SUCCESS) {
hermon_rsrc_fini(state, cleanup);
status = DDI_FAILURE;
goto rsrcinitp2_fail;
}
cleanup = HERMON_RSRC_CLEANUP_ALL;
kmem_free(rsrc_name, HERMON_RSRC_NAME_MAXLEN);
return (DDI_SUCCESS);
rsrcinitp2_fail:
kmem_free(rsrc_name, HERMON_RSRC_NAME_MAXLEN);
return (status);
}
void
hermon_rsrc_fini(hermon_state_t *state, hermon_rsrc_cleanup_level_t clean)
{
hermon_rsrc_sw_hdl_info_t hdl_info;
hermon_rsrc_hw_entry_info_t entry_info;
hermon_rsrc_mbox_info_t mbox_info;
hermon_cfg_profile_t *cfgprof;
ASSERT(state != NULL);
cfgprof = state->hs_cfg_profile;
switch (clean) {
case HERMON_RSRC_CLEANUP_ALL:
case HERMON_RSRC_CLEANUP_LEVEL31:
if (state->hs_kern_dbr) {
hermon_dbr_kern_free(state);
state->hs_kern_dbr = NULL;
}
entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_UARPG];
hermon_rsrc_hw_entries_fini(state, &entry_info);
case HERMON_RSRC_CLEANUP_LEVEL30:
hdl_info.swi_rsrcpool = NULL;
hdl_info.swi_table_ptr = state->hs_mcghdl;
hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_mcg);
hdl_info.swi_prealloc_sz = sizeof (struct hermon_sw_mcg_list_s);
hermon_rsrc_sw_handles_fini(state, &hdl_info);
case HERMON_RSRC_CLEANUP_LEVEL29:
hdl_info.swi_rsrcpool = &state->hs_rsrc_hdl[HERMON_REFCNT];
hdl_info.swi_table_ptr = NULL;
hermon_rsrc_sw_handles_fini(state, &hdl_info);
case HERMON_RSRC_CLEANUP_LEVEL28:
hdl_info.swi_rsrcpool = &state->hs_rsrc_hdl[HERMON_QPHDL];
hdl_info.swi_table_ptr = NULL;
hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_qp);
hdl_info.swi_prealloc_sz = sizeof (hermon_qphdl_t);
hermon_rsrc_sw_handles_fini(state, &hdl_info);
case HERMON_RSRC_CLEANUP_LEVEL27:
hdl_info.swi_rsrcpool = &state->hs_rsrc_hdl[HERMON_AHHDL];
hdl_info.swi_table_ptr = NULL;
hermon_rsrc_sw_handles_fini(state, &hdl_info);
case HERMON_RSRC_CLEANUP_LEVEL26:
hdl_info.swi_rsrcpool = &state->hs_rsrc_hdl[HERMON_SRQHDL];
hdl_info.swi_table_ptr = NULL;
hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_srq);
hdl_info.swi_prealloc_sz = sizeof (hermon_srqhdl_t);
hermon_rsrc_sw_handles_fini(state, &hdl_info);
case HERMON_RSRC_CLEANUP_LEVEL25:
hdl_info.swi_rsrcpool = &state->hs_rsrc_hdl[HERMON_CQHDL];
hdl_info.swi_table_ptr = NULL;
hdl_info.swi_num = ((uint64_t)1 << cfgprof->cp_log_num_cq);
hdl_info.swi_prealloc_sz = sizeof (hermon_cqhdl_t);
hermon_rsrc_sw_handles_fini(state, &hdl_info);
case HERMON_RSRC_CLEANUP_LEVEL24:
hdl_info.swi_rsrcpool = &state->hs_rsrc_hdl[HERMON_EQHDL];
hdl_info.swi_table_ptr = NULL;
hermon_rsrc_sw_handles_fini(state, &hdl_info);
case HERMON_RSRC_CLEANUP_LEVEL23:
hdl_info.swi_rsrcpool = &state->hs_rsrc_hdl[HERMON_MRHDL];
hdl_info.swi_table_ptr = NULL;
hermon_rsrc_sw_handles_fini(state, &hdl_info);
case HERMON_RSRC_CLEANUP_LEVEL22:
hdl_info.swi_rsrcpool = &state->hs_rsrc_hdl[HERMON_PDHDL];
hdl_info.swi_table_ptr = NULL;
hermon_rsrc_pd_handles_fini(state, &hdl_info);
case HERMON_RSRC_CLEANUP_LEVEL21:
case HERMON_RSRC_CLEANUP_LEVEL20:
hermon_outstanding_cmdlist_fini(state);
case HERMON_RSRC_CLEANUP_LEVEL19:
entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_EQC];
hermon_rsrc_hw_entries_fini(state, &entry_info);
case HERMON_RSRC_CLEANUP_LEVEL18:
entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_MCG];
hermon_rsrc_hw_entries_fini(state, &entry_info);
case HERMON_RSRC_CLEANUP_LEVEL17:
case HERMON_RSRC_CLEANUP_LEVEL16:
entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_SRQC];
hermon_rsrc_hw_entries_fini(state, &entry_info);
case HERMON_RSRC_CLEANUP_LEVEL15:
entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_AUXC];
hermon_rsrc_hw_entries_fini(state, &entry_info);
case HERMON_RSRC_CLEANUP_LEVEL14:
entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_ALTC];
hermon_rsrc_hw_entries_fini(state, &entry_info);
case HERMON_RSRC_CLEANUP_LEVEL13:
entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_CQC];
hermon_rsrc_hw_entries_fini(state, &entry_info);
case HERMON_RSRC_CLEANUP_LEVEL12:
entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_RDB];
hermon_rsrc_hw_entries_fini(state, &entry_info);
case HERMON_RSRC_CLEANUP_LEVEL11:
entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_QPC];
hermon_rsrc_hw_entries_fini(state, &entry_info);
case HERMON_RSRC_CLEANUP_LEVEL10EQ:
entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_CMPT_EQC];
hermon_rsrc_hw_entries_fini(state, &entry_info);
case HERMON_RSRC_CLEANUP_LEVEL10CQ:
entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_CMPT_CQC];
hermon_rsrc_hw_entries_fini(state, &entry_info);
case HERMON_RSRC_CLEANUP_LEVEL10SRQ:
entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_CMPT_SRQC];
hermon_rsrc_hw_entries_fini(state, &entry_info);
case HERMON_RSRC_CLEANUP_LEVEL10QP:
entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_CMPT_QPC];
hermon_rsrc_hw_entries_fini(state, &entry_info);
case HERMON_RSRC_CLEANUP_LEVEL10:
entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_DMPT];
hermon_rsrc_hw_entries_fini(state, &entry_info);
case HERMON_RSRC_CLEANUP_LEVEL9:
entry_info.hwi_rsrcpool = &state->hs_rsrc_hdl[HERMON_MTT];
hermon_rsrc_hw_entries_fini(state, &entry_info);
break;
case HERMON_RSRC_CLEANUP_PHASE1_COMPLETE:
hermon_intr_inmbox_list_fini(state);
case HERMON_RSRC_CLEANUP_LEVEL7:
mbox_info.mbi_rsrcpool =
&state->hs_rsrc_hdl[HERMON_INTR_IN_MBOX];
hermon_rsrc_mbox_fini(state, &mbox_info);
case HERMON_RSRC_CLEANUP_LEVEL6:
hermon_inmbox_list_fini(state);
case HERMON_RSRC_CLEANUP_LEVEL5:
mbox_info.mbi_rsrcpool = &state->hs_rsrc_hdl[HERMON_IN_MBOX];
hermon_rsrc_mbox_fini(state, &mbox_info);
case HERMON_RSRC_CLEANUP_LEVEL4:
hermon_intr_outmbox_list_fini(state);
case HERMON_RSRC_CLEANUP_LEVEL3:
mbox_info.mbi_rsrcpool =
&state->hs_rsrc_hdl[HERMON_INTR_OUT_MBOX];
hermon_rsrc_mbox_fini(state, &mbox_info);
case HERMON_RSRC_CLEANUP_LEVEL2:
hermon_outmbox_list_fini(state);
case HERMON_RSRC_CLEANUP_LEVEL1:
mbox_info.mbi_rsrcpool = &state->hs_rsrc_hdl[HERMON_OUT_MBOX];
hermon_rsrc_mbox_fini(state, &mbox_info);
case HERMON_RSRC_CLEANUP_LEVEL0:
kmem_free(state->hs_rsrc_hdl, HERMON_NUM_RESOURCES *
sizeof (hermon_rsrc_pool_info_t));
kmem_cache_destroy(state->hs_rsrc_cache);
break;
default:
HERMON_WARNING(state, "unexpected resource cleanup level");
break;
}
}
static int
hermon_rsrc_mbox_init(hermon_state_t *state, hermon_rsrc_mbox_info_t *info)
{
hermon_rsrc_pool_info_t *rsrc_pool;
hermon_rsrc_priv_mbox_t *priv;
ASSERT(state != NULL);
ASSERT(info != NULL);
rsrc_pool = info->mbi_rsrcpool;
ASSERT(rsrc_pool != NULL);
priv = kmem_zalloc(sizeof (hermon_rsrc_priv_mbox_t), KM_SLEEP);
priv->pmb_dip = state->hs_dip;
priv->pmb_devaccattr = state->hs_reg_accattr;
priv->pmb_xfer_mode = DDI_DMA_CONSISTENT;
hermon_dma_attr_init(state, &priv->pmb_dmaattr);
priv->pmb_dmaattr.dma_attr_align = HERMON_MBOX_ALIGN;
priv->pmb_dmaattr.dma_attr_sgllen = 1;
priv->pmb_dmaattr.dma_attr_flags = 0;
rsrc_pool->rsrc_private = priv;
ASSERT(rsrc_pool->rsrc_loc == HERMON_IN_SYSMEM);
rsrc_pool->rsrc_start = NULL;
rsrc_pool->rsrc_vmp = NULL;
return (DDI_SUCCESS);
}
static void
hermon_rsrc_mbox_fini(hermon_state_t *state, hermon_rsrc_mbox_info_t *info)
{
hermon_rsrc_pool_info_t *rsrc_pool;
ASSERT(state != NULL);
ASSERT(info != NULL);
rsrc_pool = info->mbi_rsrcpool;
ASSERT(rsrc_pool != NULL);
kmem_free(rsrc_pool->rsrc_private, sizeof (hermon_rsrc_priv_mbox_t));
}
int
hermon_rsrc_hw_entries_init(hermon_state_t *state,
hermon_rsrc_hw_entry_info_t *info)
{
hermon_rsrc_pool_info_t *rsrc_pool;
hermon_rsrc_t *rsvd_rsrc = NULL;
vmem_t *vmp;
uint64_t num_hwentry, max_hwentry, num_prealloc;
int status;
ASSERT(state != NULL);
ASSERT(info != NULL);
rsrc_pool = info->hwi_rsrcpool;
ASSERT(rsrc_pool != NULL);
num_hwentry = info->hwi_num;
max_hwentry = info->hwi_max;
num_prealloc = info->hwi_prealloc;
if (hermon_rsrc_verbose) {
IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entries_init: "
"rsrc_type (0x%x) num (%llx) max (0x%llx) prealloc "
"(0x%llx)", rsrc_pool->rsrc_type, (longlong_t)num_hwentry,
(longlong_t)max_hwentry, (longlong_t)num_prealloc);
}
if (num_hwentry > max_hwentry) {
return (DDI_FAILURE);
}
if (rsrc_pool->rsrc_start == 0) {
rsrc_pool->rsrc_start = (void *)(uintptr_t)0x10000000;
if (hermon_rsrc_verbose) {
IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entries_init:"
" rsrc_type (0x%x) rsrc_start set (0x%lx)",
rsrc_pool->rsrc_type, rsrc_pool->rsrc_start);
}
}
if (rsrc_pool->rsrc_quantum != 0) {
vmp = vmem_create(info->hwi_rsrcname,
(void *)(uintptr_t)rsrc_pool->rsrc_start,
rsrc_pool->rsrc_pool_size, rsrc_pool->rsrc_quantum,
NULL, NULL, NULL, 0, VM_SLEEP);
if (vmp == NULL) {
return (DDI_FAILURE);
}
rsrc_pool->rsrc_vmp = vmp;
if (hermon_rsrc_verbose) {
IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entries_init:"
" rsrc_type (0x%x) created vmem arena for rsrc",
rsrc_pool->rsrc_type);
}
} else {
rsrc_pool->rsrc_vmp = NULL;
if (hermon_rsrc_verbose) {
IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entries_init:"
" rsrc_type (0x%x) vmem arena not required",
rsrc_pool->rsrc_type);
}
}
if (num_prealloc != 0) {
status = hermon_rsrc_alloc(state, rsrc_pool->rsrc_type,
num_prealloc, HERMON_SLEEP, &rsvd_rsrc);
if (status != DDI_SUCCESS) {
if (rsrc_pool->rsrc_vmp != NULL) {
vmem_destroy(rsrc_pool->rsrc_vmp);
}
return (DDI_FAILURE);
}
}
rsrc_pool->rsrc_private = rsvd_rsrc;
return (DDI_SUCCESS);
}
void
hermon_rsrc_hw_entries_fini(hermon_state_t *state,
hermon_rsrc_hw_entry_info_t *info)
{
hermon_rsrc_pool_info_t *rsrc_pool;
hermon_rsrc_t *rsvd_rsrc;
ASSERT(state != NULL);
ASSERT(info != NULL);
rsrc_pool = info->hwi_rsrcpool;
ASSERT(rsrc_pool != NULL);
rsvd_rsrc = (hermon_rsrc_t *)rsrc_pool->rsrc_private;
if (rsvd_rsrc != NULL) {
hermon_rsrc_free(state, &rsvd_rsrc);
}
if (rsrc_pool->rsrc_vmp != NULL) {
vmem_destroy(rsrc_pool->rsrc_vmp);
}
}
static int
hermon_rsrc_sw_handles_init(hermon_state_t *state,
hermon_rsrc_sw_hdl_info_t *info)
{
hermon_rsrc_pool_info_t *rsrc_pool;
uint64_t num_swhdl, max_swhdl, prealloc_sz;
ASSERT(state != NULL);
ASSERT(info != NULL);
rsrc_pool = info->swi_rsrcpool;
ASSERT(rsrc_pool != NULL);
num_swhdl = info->swi_num;
max_swhdl = info->swi_max;
prealloc_sz = info->swi_prealloc_sz;
if (num_swhdl > max_swhdl) {
return (DDI_FAILURE);
}
if (info->swi_flags & HERMON_SWHDL_KMEMCACHE_INIT) {
rsrc_pool->rsrc_private = kmem_cache_create(
info->swi_rsrcname, rsrc_pool->rsrc_quantum, 0,
info->swi_constructor, info->swi_destructor, NULL,
rsrc_pool->rsrc_state, NULL, 0);
}
if (info->swi_flags & HERMON_SWHDL_TABLE_INIT) {
info->swi_table_ptr = kmem_zalloc(num_swhdl * prealloc_sz,
KM_SLEEP);
}
return (DDI_SUCCESS);
}
static void
hermon_rsrc_sw_handles_fini(hermon_state_t *state,
hermon_rsrc_sw_hdl_info_t *info)
{
hermon_rsrc_pool_info_t *rsrc_pool;
uint64_t num_swhdl, prealloc_sz;
ASSERT(state != NULL);
ASSERT(info != NULL);
rsrc_pool = info->swi_rsrcpool;
num_swhdl = info->swi_num;
prealloc_sz = info->swi_prealloc_sz;
if (rsrc_pool != NULL) {
kmem_cache_destroy(rsrc_pool->rsrc_private);
}
if (info->swi_table_ptr != NULL) {
kmem_free(info->swi_table_ptr, num_swhdl * prealloc_sz);
}
}
static int
hermon_rsrc_pd_handles_init(hermon_state_t *state,
hermon_rsrc_sw_hdl_info_t *info)
{
hermon_rsrc_pool_info_t *rsrc_pool;
vmem_t *vmp;
char vmem_name[HERMON_RSRC_NAME_MAXLEN];
int status;
ASSERT(state != NULL);
ASSERT(info != NULL);
rsrc_pool = info->swi_rsrcpool;
ASSERT(rsrc_pool != NULL);
status = hermon_rsrc_sw_handles_init(state, info);
if (status != DDI_SUCCESS) {
return (DDI_FAILURE);
}
HERMON_RSRC_NAME(vmem_name, HERMON_PDHDL_VMEM);
vmp = vmem_create(vmem_name, (caddr_t)1, info->swi_num, 1, NULL,
NULL, NULL, 0, VM_SLEEP | VMC_IDENTIFIER);
if (vmp == NULL) {
info->swi_table_ptr = NULL;
hermon_rsrc_sw_handles_fini(state, info);
return (DDI_FAILURE);
}
rsrc_pool->rsrc_vmp = vmp;
return (DDI_SUCCESS);
}
static void
hermon_rsrc_pd_handles_fini(hermon_state_t *state,
hermon_rsrc_sw_hdl_info_t *info)
{
hermon_rsrc_pool_info_t *rsrc_pool;
ASSERT(state != NULL);
ASSERT(info != NULL);
rsrc_pool = info->swi_rsrcpool;
vmem_destroy(rsrc_pool->rsrc_vmp);
hermon_rsrc_sw_handles_fini(state, info);
}
static int
hermon_rsrc_mbox_alloc(hermon_rsrc_pool_info_t *pool_info, uint_t num,
hermon_rsrc_t *hdl)
{
hermon_rsrc_priv_mbox_t *priv;
caddr_t kaddr;
size_t real_len, temp_len;
int status;
ASSERT(pool_info != NULL);
ASSERT(hdl != NULL);
priv = pool_info->rsrc_private;
ASSERT(priv != NULL);
status = ddi_dma_alloc_handle(priv->pmb_dip, &priv->pmb_dmaattr,
DDI_DMA_SLEEP, NULL, &hdl->hr_dmahdl);
if (status != DDI_SUCCESS) {
return (DDI_FAILURE);
}
temp_len = (num << pool_info->rsrc_shift);
status = ddi_dma_mem_alloc(hdl->hr_dmahdl, temp_len,
&priv->pmb_devaccattr, priv->pmb_xfer_mode, DDI_DMA_SLEEP,
NULL, &kaddr, &real_len, &hdl->hr_acchdl);
if (status != DDI_SUCCESS) {
ddi_dma_free_handle(&hdl->hr_dmahdl);
return (DDI_FAILURE);
}
hdl->hr_addr = (void *)kaddr;
hdl->hr_len = (uint32_t)real_len;
return (DDI_SUCCESS);
}
static void
hermon_rsrc_mbox_free(hermon_rsrc_t *hdl)
{
ASSERT(hdl != NULL);
ddi_dma_mem_free(&hdl->hr_acchdl);
ddi_dma_free_handle(&hdl->hr_dmahdl);
}
static int
hermon_rsrc_hw_entry_alloc(hermon_rsrc_pool_info_t *pool_info, uint_t num,
uint_t num_align, uint_t sleepflag, hermon_rsrc_t *hdl)
{
void *addr;
uint64_t offset;
uint32_t align;
int status;
int flag;
ASSERT(pool_info != NULL);
ASSERT(hdl != NULL);
flag = (sleepflag == HERMON_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
hdl->hr_len = (num << pool_info->rsrc_shift);
align = (num_align << pool_info->rsrc_shift);
addr = vmem_xalloc(pool_info->rsrc_vmp, hdl->hr_len,
align, 0, 0, NULL, NULL, flag | VM_FIRSTFIT);
if (addr == NULL) {
return (DDI_FAILURE);
}
hdl->hr_acchdl = NULL;
offset = (uintptr_t)addr - (uintptr_t)pool_info->rsrc_start;
hdl->hr_addr = addr;
hdl->hr_indx = offset >> pool_info->rsrc_shift;
if (pool_info->rsrc_loc == HERMON_IN_ICM) {
int num_to_hdl;
hermon_rsrc_type_t rsrc_type = pool_info->rsrc_type;
num_to_hdl = (rsrc_type == HERMON_QPC ||
rsrc_type == HERMON_CQC || rsrc_type == HERMON_SRQC);
status = hermon_rsrc_hw_entry_icm_confirm(pool_info, num, hdl,
num_to_hdl);
if (status != DDI_SUCCESS) {
return (DDI_FAILURE);
}
hdl->hr_addr = NULL;
}
return (DDI_SUCCESS);
}
int
hermon_rsrc_hw_entry_reserve(hermon_rsrc_pool_info_t *pool_info, uint_t num,
uint_t num_align, uint_t sleepflag, hermon_rsrc_t *hdl)
{
void *addr;
uint64_t offset;
uint32_t align;
int flag;
ASSERT(pool_info != NULL);
ASSERT(hdl != NULL);
ASSERT(pool_info->rsrc_loc == HERMON_IN_ICM);
flag = (sleepflag == HERMON_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
hdl->hr_len = (num << pool_info->rsrc_shift);
align = (num_align << pool_info->rsrc_shift);
addr = vmem_xalloc(pool_info->rsrc_vmp, hdl->hr_len,
align, 0, 0, NULL, NULL, flag | VM_FIRSTFIT);
if (addr == NULL) {
return (DDI_FAILURE);
}
hdl->hr_acchdl = NULL;
offset = (uintptr_t)addr - (uintptr_t)pool_info->rsrc_start;
hdl->hr_addr = NULL;
hdl->hr_indx = offset >> pool_info->rsrc_shift;
return (DDI_SUCCESS);
}
static void
hermon_rsrc_hw_entry_free(hermon_rsrc_pool_info_t *pool_info,
hermon_rsrc_t *hdl)
{
void *addr;
uint64_t offset;
int status;
ASSERT(pool_info != NULL);
ASSERT(hdl != NULL);
offset = hdl->hr_indx << pool_info->rsrc_shift;
addr = (void *)(uintptr_t)(offset + (uintptr_t)pool_info->rsrc_start);
vmem_xfree(pool_info->rsrc_vmp, addr, hdl->hr_len);
if (pool_info->rsrc_loc == HERMON_IN_ICM) {
int num_to_hdl;
hermon_rsrc_type_t rsrc_type = pool_info->rsrc_type;
num_to_hdl = (rsrc_type == HERMON_QPC ||
rsrc_type == HERMON_CQC || rsrc_type == HERMON_SRQC);
status = hermon_rsrc_hw_entry_icm_free(pool_info, hdl,
num_to_hdl);
if (status != DDI_SUCCESS)
HERMON_WARNING(pool_info->rsrc_state,
"failure in hw_entry_free");
}
}
static int
hermon_rsrc_hw_entry_icm_confirm(hermon_rsrc_pool_info_t *pool_info, uint_t num,
hermon_rsrc_t *hdl, int num_to_hdl)
{
hermon_state_t *state;
hermon_icm_table_t *icm_table;
uint8_t *bitmap;
hermon_dma_info_t *dma_info;
hermon_rsrc_type_t type;
uint32_t rindx, span_offset;
uint32_t span_avail;
int num_backed;
int status;
uint32_t index1, index2;
state = pool_info->rsrc_state;
type = pool_info->rsrc_type;
icm_table = &state->hs_icm[type];
rindx = hdl->hr_indx;
hermon_index(index1, index2, rindx, icm_table, span_offset);
if (hermon_rsrc_verbose) {
IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entry_icm_confirm: "
"type (0x%x) num (0x%x) length (0x%x) index (0x%x, 0x%x): ",
type, num, hdl->hr_len, index1, index2);
}
mutex_enter(&icm_table->icm_table_lock);
hermon_bitmap(bitmap, dma_info, icm_table, index1, num_to_hdl);
while (num) {
#ifndef __lock_lint
while (icm_table->icm_busy) {
cv_wait(&icm_table->icm_table_cv,
&icm_table->icm_table_lock);
}
#endif
if (!HERMON_BMAP_BIT_ISSET(bitmap, index2)) {
icm_table->icm_busy = 1;
mutex_exit(&icm_table->icm_table_lock);
status = hermon_icm_alloc(state, type, index1, index2);
mutex_enter(&icm_table->icm_table_lock);
icm_table->icm_busy = 0;
cv_broadcast(&icm_table->icm_table_cv);
if (status != DDI_SUCCESS) {
goto fail_alloc;
}
if (hermon_rsrc_verbose) {
IBTF_DPRINTF_L2("hermon", "hermon_rsrc_"
"hw_entry_icm_confirm: ALLOCATED ICM: "
"type (0x%x) index (0x%x, 0x%x)",
type, index1, index2);
}
}
span_avail = icm_table->span - span_offset;
if (num > span_avail) {
num_backed = span_avail;
} else {
num_backed = num;
}
dma_info[index2].icm_refcnt += num_backed;
rindx += num_backed;
num -= num_backed;
if (hermon_rsrc_verbose) {
IBTF_DPRINTF_L2("ALLOC", "ICM type (0x%x) index "
"(0x%x, 0x%x) num_backed (0x%x)",
type, index1, index2, num_backed);
IBTF_DPRINTF_L2("ALLOC", "ICM type (0x%x) refcnt now "
"(0x%x) num_remaining (0x%x)", type,
dma_info[index2].icm_refcnt, num);
}
if (num == 0)
break;
hermon_index(index1, index2, rindx, icm_table, span_offset);
hermon_bitmap(bitmap, dma_info, icm_table, index1, num_to_hdl);
}
mutex_exit(&icm_table->icm_table_lock);
return (DDI_SUCCESS);
fail_alloc:
if (hermon_rsrc_verbose) {
IBTF_DPRINTF_L2("hermon", "hermon_rsrc_"
"hw_entry_icm_confirm: FAILED ICM ALLOC: "
"type (0x%x) num remaind (0x%x) index (0x%x, 0x%x)"
"refcnt (0x%x)", type, num, index1, index2,
icm_table->icm_dma[index1][index2].icm_refcnt);
}
IBTF_DPRINTF_L2("hermon", "WARNING: "
"unimplemented fail code in hermon_rsrc_hw_entry_icm_alloc\n");
#if needs_work
while (index-- != start) {
HERMON_WARNING(state, "unable to allocate ICM memory: "
"UNIMPLEMENTED HANDLING!!");
}
#else
cmn_err(CE_WARN,
"unimplemented fail code in hermon_rsrc_hw_entry_icm_alloc\n");
#endif
mutex_exit(&icm_table->icm_table_lock);
HERMON_WARNING(state, "unable to allocate ICM memory");
return (DDI_FAILURE);
}
static int
hermon_rsrc_hw_entry_icm_free(hermon_rsrc_pool_info_t *pool_info,
hermon_rsrc_t *hdl, int num_to_hdl)
{
hermon_state_t *state;
hermon_icm_table_t *icm_table;
uint8_t *bitmap;
hermon_dma_info_t *dma_info;
hermon_rsrc_type_t type;
uint32_t span_offset;
uint32_t span_remain;
int num_freed;
int num;
uint32_t index1, index2, rindx;
state = pool_info->rsrc_state;
type = pool_info->rsrc_type;
icm_table = &state->hs_icm[type];
rindx = hdl->hr_indx;
hermon_index(index1, index2, rindx, icm_table, span_offset);
hermon_bitmap(bitmap, dma_info, icm_table, index1, num_to_hdl);
num = hdl->hr_len >> pool_info->rsrc_shift;
if (hermon_rsrc_verbose) {
IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entry_icm_free: "
"type (0x%x) num (0x%x) length (0x%x) index (0x%x, 0x%x)",
type, num, hdl->hr_len, index1, index2);
}
mutex_enter(&icm_table->icm_table_lock);
while (num) {
span_remain = icm_table->span - span_offset;
if (num > span_remain) {
num_freed = span_remain;
} else {
num_freed = num;
}
dma_info[index2].icm_refcnt -= num_freed;
num -= num_freed;
rindx += num_freed;
if (hermon_rsrc_verbose) {
IBTF_DPRINTF_L2("FREE", "ICM type (0x%x) index "
"(0x%x, 0x%x) num_freed (0x%x)", type,
index1, index2, num_freed);
IBTF_DPRINTF_L2("FREE", "ICM type (0x%x) refcnt now "
"(0x%x) num remaining (0x%x)", type,
icm_table->icm_dma[index1][index2].icm_refcnt, num);
}
#if HERMON_ICM_FREE_ENABLED
if ((index1 != 0 || index2 != 0) &&
(dma_info[index2].icm_refcnt == 0)) {
if (hermon_rsrc_verbose) {
IBTF_DPRINTF_L2("hermon", "hermon_rsrc_hw_entry"
"_icm_free: freeing ICM type (0x%x) index"
" (0x%x, 0x%x)", type, index1, index2);
}
hermon_icm_free(state, type, index1, index2);
}
#endif
if (num == 0)
break;
hermon_index(index1, index2, rindx, icm_table, span_offset);
hermon_bitmap(bitmap, dma_info, icm_table, index1, num_to_hdl);
}
mutex_exit(&icm_table->icm_table_lock);
return (DDI_SUCCESS);
}
static int
hermon_rsrc_swhdl_alloc(hermon_rsrc_pool_info_t *pool_info, uint_t sleepflag,
hermon_rsrc_t *hdl)
{
void *addr;
int flag;
ASSERT(pool_info != NULL);
ASSERT(hdl != NULL);
flag = (sleepflag == HERMON_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
addr = kmem_cache_alloc(pool_info->rsrc_private, flag);
if (addr == NULL) {
return (DDI_FAILURE);
}
hdl->hr_len = pool_info->rsrc_quantum;
hdl->hr_addr = addr;
return (DDI_SUCCESS);
}
static void
hermon_rsrc_swhdl_free(hermon_rsrc_pool_info_t *pool_info, hermon_rsrc_t *hdl)
{
ASSERT(pool_info != NULL);
ASSERT(hdl != NULL);
kmem_cache_free(pool_info->rsrc_private, hdl->hr_addr);
}
static int
hermon_rsrc_pdhdl_alloc(hermon_rsrc_pool_info_t *pool_info, uint_t sleepflag,
hermon_rsrc_t *hdl)
{
hermon_pdhdl_t addr;
void *tmpaddr;
int flag, status;
ASSERT(pool_info != NULL);
ASSERT(hdl != NULL);
status = hermon_rsrc_swhdl_alloc(pool_info, sleepflag, hdl);
if (status != DDI_SUCCESS) {
return (DDI_FAILURE);
}
addr = (hermon_pdhdl_t)hdl->hr_addr;
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*addr))
flag = (sleepflag == HERMON_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
tmpaddr = vmem_alloc(pool_info->rsrc_vmp, 1, flag);
if (tmpaddr == NULL) {
hermon_rsrc_swhdl_free(pool_info, hdl);
return (DDI_FAILURE);
}
addr->pd_pdnum = (uint32_t)(uintptr_t)tmpaddr;
addr->pd_rsrcp = hdl;
hdl->hr_indx = addr->pd_pdnum;
return (DDI_SUCCESS);
}
static void
hermon_rsrc_pdhdl_free(hermon_rsrc_pool_info_t *pool_info, hermon_rsrc_t *hdl)
{
ASSERT(pool_info != NULL);
ASSERT(hdl != NULL);
vmem_free(pool_info->rsrc_vmp, (void *)(uintptr_t)hdl->hr_indx, 1);
hermon_rsrc_swhdl_free(pool_info, hdl);
}
static int
hermon_rsrc_pdhdl_constructor(void *pd, void *priv, int flags)
{
hermon_pdhdl_t pdhdl;
hermon_state_t *state;
pdhdl = (hermon_pdhdl_t)pd;
state = (hermon_state_t *)priv;
mutex_init(&pdhdl->pd_lock, NULL, MUTEX_DRIVER,
DDI_INTR_PRI(state->hs_intrmsi_pri));
return (DDI_SUCCESS);
}
static void
hermon_rsrc_pdhdl_destructor(void *pd, void *priv)
{
hermon_pdhdl_t pdhdl;
pdhdl = (hermon_pdhdl_t)pd;
mutex_destroy(&pdhdl->pd_lock);
}
static int
hermon_rsrc_cqhdl_constructor(void *cq, void *priv, int flags)
{
hermon_cqhdl_t cqhdl;
hermon_state_t *state;
cqhdl = (hermon_cqhdl_t)cq;
state = (hermon_state_t *)priv;
mutex_init(&cqhdl->cq_lock, NULL, MUTEX_DRIVER,
DDI_INTR_PRI(state->hs_intrmsi_pri));
return (DDI_SUCCESS);
}
static void
hermon_rsrc_cqhdl_destructor(void *cq, void *priv)
{
hermon_cqhdl_t cqhdl;
cqhdl = (hermon_cqhdl_t)cq;
mutex_destroy(&cqhdl->cq_lock);
}
static int
hermon_rsrc_qphdl_constructor(void *qp, void *priv, int flags)
{
hermon_qphdl_t qphdl;
hermon_state_t *state;
qphdl = (hermon_qphdl_t)qp;
state = (hermon_state_t *)priv;
mutex_init(&qphdl->qp_lock, NULL, MUTEX_DRIVER,
DDI_INTR_PRI(state->hs_intrmsi_pri));
return (DDI_SUCCESS);
}
static void
hermon_rsrc_qphdl_destructor(void *qp, void *priv)
{
hermon_qphdl_t qphdl;
qphdl = (hermon_qphdl_t)qp;
mutex_destroy(&qphdl->qp_lock);
}
static int
hermon_rsrc_srqhdl_constructor(void *srq, void *priv, int flags)
{
hermon_srqhdl_t srqhdl;
hermon_state_t *state;
srqhdl = (hermon_srqhdl_t)srq;
state = (hermon_state_t *)priv;
mutex_init(&srqhdl->srq_lock, NULL, MUTEX_DRIVER,
DDI_INTR_PRI(state->hs_intrmsi_pri));
return (DDI_SUCCESS);
}
static void
hermon_rsrc_srqhdl_destructor(void *srq, void *priv)
{
hermon_srqhdl_t srqhdl;
srqhdl = (hermon_srqhdl_t)srq;
mutex_destroy(&srqhdl->srq_lock);
}
static int
hermon_rsrc_refcnt_constructor(void *rc, void *priv, int flags)
{
hermon_sw_refcnt_t *refcnt;
hermon_state_t *state;
refcnt = (hermon_sw_refcnt_t *)rc;
state = (hermon_state_t *)priv;
mutex_init(&refcnt->swrc_lock, NULL, MUTEX_DRIVER,
DDI_INTR_PRI(state->hs_intrmsi_pri));
return (DDI_SUCCESS);
}
static void
hermon_rsrc_refcnt_destructor(void *rc, void *priv)
{
hermon_sw_refcnt_t *refcnt;
refcnt = (hermon_sw_refcnt_t *)rc;
mutex_destroy(&refcnt->swrc_lock);
}
static int
hermon_rsrc_ahhdl_constructor(void *ah, void *priv, int flags)
{
hermon_ahhdl_t ahhdl;
hermon_state_t *state;
ahhdl = (hermon_ahhdl_t)ah;
state = (hermon_state_t *)priv;
mutex_init(&ahhdl->ah_lock, NULL, MUTEX_DRIVER,
DDI_INTR_PRI(state->hs_intrmsi_pri));
return (DDI_SUCCESS);
}
static void
hermon_rsrc_ahhdl_destructor(void *ah, void *priv)
{
hermon_ahhdl_t ahhdl;
ahhdl = (hermon_ahhdl_t)ah;
mutex_destroy(&ahhdl->ah_lock);
}
static int
hermon_rsrc_mrhdl_constructor(void *mr, void *priv, int flags)
{
hermon_mrhdl_t mrhdl;
hermon_state_t *state;
mrhdl = (hermon_mrhdl_t)mr;
state = (hermon_state_t *)priv;
mutex_init(&mrhdl->mr_lock, NULL, MUTEX_DRIVER,
DDI_INTR_PRI(state->hs_intrmsi_pri));
return (DDI_SUCCESS);
}
static void
hermon_rsrc_mrhdl_destructor(void *mr, void *priv)
{
hermon_mrhdl_t mrhdl;
mrhdl = (hermon_mrhdl_t)mr;
mutex_destroy(&mrhdl->mr_lock);
}
static int
hermon_rsrc_mcg_entry_get_size(hermon_state_t *state, uint_t *mcg_size_shift)
{
uint_t num_qp_per_mcg, max_qp_per_mcg, log2;
num_qp_per_mcg = state->hs_cfg_profile->cp_num_qp_per_mcg + 8;
log2 = highbit(num_qp_per_mcg);
if (ISP2(num_qp_per_mcg)) {
log2 = log2 - 1;
}
state->hs_cfg_profile->cp_num_qp_per_mcg = (1 << log2) - 8;
num_qp_per_mcg = state->hs_cfg_profile->cp_num_qp_per_mcg;
max_qp_per_mcg = (1 << state->hs_devlim.log_max_qp_mcg);
if (num_qp_per_mcg > max_qp_per_mcg) {
return (DDI_FAILURE);
}
*mcg_size_shift = log2 + 2;
return (DDI_SUCCESS);
}