#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/bitmap.h>
#include <sys/ib/adapters/tavor/tavor.h>
static void tavor_srq_sgl_to_logwqesz(tavor_state_t *state, uint_t num_sgl,
tavor_qp_wq_type_t wq_type, uint_t *logwqesz, uint_t *max_sgl);
int
tavor_srq_alloc(tavor_state_t *state, tavor_srq_info_t *srqinfo,
uint_t sleepflag, tavor_srq_options_t *op)
{
ibt_srq_hdl_t ibt_srqhdl;
tavor_pdhdl_t pd;
ibt_srq_sizes_t *sizes;
ibt_srq_sizes_t *real_sizes;
tavor_srqhdl_t *srqhdl;
ibt_srq_flags_t flags;
tavor_rsrc_t *srqc, *rsrc;
tavor_hw_srqc_t srqc_entry;
uint32_t *buf;
tavor_srqhdl_t srq;
tavor_umap_db_entry_t *umapdb;
ibt_mr_attr_t mr_attr;
tavor_mr_options_t mr_op;
tavor_mrhdl_t mr;
uint64_t addr;
uint64_t value, srq_desc_off;
uint32_t lkey;
uint32_t log_srq_size;
uint32_t uarpg;
uint_t wq_location, dma_xfer_mode, srq_is_umap;
int flag, status;
uint_t max_sgl;
uint_t wqesz;
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sizes))
if (op == NULL) {
wq_location = TAVOR_QUEUE_LOCATION_NORMAL;
} else {
wq_location = op->srqo_wq_loc;
}
real_sizes = srqinfo->srqi_real_sizes;
sizes = srqinfo->srqi_sizes;
pd = srqinfo->srqi_pd;
ibt_srqhdl = srqinfo->srqi_ibt_srqhdl;
flags = srqinfo->srqi_flags;
srqhdl = srqinfo->srqi_srqhdl;
srq_is_umap = (flags & IBT_SRQ_USER_MAP) ? 1 : 0;
if (srq_is_umap) {
status = tavor_umap_db_find(state->ts_instance, ddi_get_pid(),
MLNX_UMAP_UARPG_RSRC, &value, 0, NULL);
if (status != DDI_SUCCESS) {
goto srqalloc_fail3;
}
uarpg = ((tavor_rsrc_t *)(uintptr_t)value)->tr_indx;
}
tavor_pd_refcnt_inc(pd);
status = tavor_rsrc_alloc(state, TAVOR_SRQC, 1, sleepflag, &srqc);
if (status != DDI_SUCCESS) {
goto srqalloc_fail1;
}
status = tavor_rsrc_alloc(state, TAVOR_SRQHDL, 1, sleepflag, &rsrc);
if (status != DDI_SUCCESS) {
goto srqalloc_fail2;
}
srq = (tavor_srqhdl_t)rsrc->tr_addr;
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*srq))
srq->srq_srqnum = srqc->tr_indx;
if (srq_is_umap) {
umapdb = tavor_umap_db_alloc(state->ts_instance,
srq->srq_srqnum, MLNX_UMAP_SRQMEM_RSRC,
(uint64_t)(uintptr_t)rsrc);
if (umapdb == NULL) {
goto srqalloc_fail3;
}
}
sizes->srq_wr_sz = max(sizes->srq_wr_sz, TAVOR_SRQ_MIN_SIZE);
log_srq_size = highbit(sizes->srq_wr_sz);
if (ISP2(sizes->srq_wr_sz)) {
log_srq_size = log_srq_size - 1;
}
if (log_srq_size > state->ts_cfg_profile->cp_log_max_srq_sz) {
goto srqalloc_fail4;
}
max_sgl = state->ts_cfg_profile->cp_srq_max_sgl;
if (sizes->srq_sgl_sz > max_sgl) {
goto srqalloc_fail4;
}
tavor_srq_sgl_to_logwqesz(state, sizes->srq_sgl_sz,
TAVOR_QP_WQ_TYPE_RECVQ, &srq->srq_wq_log_wqesz,
&srq->srq_wq_sgl);
wqesz = (1 << srq->srq_wq_log_wqesz);
srq->srq_wqinfo.qa_size = (1 << log_srq_size) * wqesz;
srq->srq_wqinfo.qa_alloc_align = PAGESIZE;
srq->srq_wqinfo.qa_bind_align = PAGESIZE;
if (srq_is_umap) {
srq->srq_wqinfo.qa_location = TAVOR_QUEUE_LOCATION_USERLAND;
} else {
srq->srq_wqinfo.qa_location = wq_location;
}
status = tavor_queue_alloc(state, &srq->srq_wqinfo, sleepflag);
if (status != DDI_SUCCESS) {
goto srqalloc_fail4;
}
buf = (uint32_t *)srq->srq_wqinfo.qa_buf_aligned;
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*buf))
flag = (sleepflag == TAVOR_SLEEP) ? IBT_MR_SLEEP :
IBT_MR_NOSLEEP;
mr_attr.mr_vaddr = (uint64_t)(uintptr_t)buf;
mr_attr.mr_len = srq->srq_wqinfo.qa_size;
mr_attr.mr_as = NULL;
mr_attr.mr_flags = flag | IBT_MR_ENABLE_LOCAL_WRITE;
if (srq_is_umap) {
mr_op.mro_bind_type = state->ts_cfg_profile->cp_iommu_bypass;
} else {
if (wq_location == TAVOR_QUEUE_LOCATION_NORMAL) {
mr_op.mro_bind_type =
state->ts_cfg_profile->cp_iommu_bypass;
dma_xfer_mode =
state->ts_cfg_profile->cp_streaming_consistent;
if (dma_xfer_mode == DDI_DMA_STREAMING) {
mr_attr.mr_flags |= IBT_MR_NONCOHERENT;
}
} else {
mr_op.mro_bind_type = TAVOR_BINDMEM_BYPASS;
}
}
mr_op.mro_bind_dmahdl = srq->srq_wqinfo.qa_dmahdl;
mr_op.mro_bind_override_addr = 1;
status = tavor_mr_register(state, pd, &mr_attr, &mr, &mr_op);
if (status != DDI_SUCCESS) {
goto srqalloc_fail5;
}
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mr))
addr = mr->mr_bindinfo.bi_addr;
lkey = mr->mr_lkey;
srq_desc_off = (uint64_t)(uintptr_t)srq->srq_wqinfo.qa_buf_aligned -
(uint64_t)mr->mr_bindinfo.bi_addr;
srq->srq_wrid_wql = tavor_wrid_wql_create(state);
if (srq->srq_wrid_wql == NULL) {
goto srqalloc_fail6;
}
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*(srq->srq_wrid_wql)))
srq->srq_wridlist = tavor_wrid_get_list(1 << log_srq_size);
if (srq->srq_wridlist == NULL) {
goto srqalloc_fail7;
}
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*(srq->srq_wridlist)))
srq->srq_wridlist->wl_srq_en = 1;
srq->srq_wridlist->wl_free_list_indx = -1;
if (real_sizes != NULL) {
real_sizes->srq_wr_sz = (1 << log_srq_size);
real_sizes->srq_sgl_sz = srq->srq_wq_sgl;
}
bzero(&srqc_entry, sizeof (tavor_hw_srqc_t));
srqc_entry.wqe_addr_h = (addr >> 32);
srqc_entry.next_wqe_addr_l = 0;
srqc_entry.ds = (wqesz >> 4);
srqc_entry.state = TAVOR_SRQ_STATE_HW_OWNER;
srqc_entry.pd = pd->pd_pdnum;
srqc_entry.lkey = lkey;
srqc_entry.wqe_cnt = 0;
if (srq_is_umap) {
srqc_entry.uar = uarpg;
} else {
srqc_entry.uar = 0;
}
status = tavor_cmn_ownership_cmd_post(state, SW2HW_SRQ, &srqc_entry,
sizeof (tavor_hw_srqc_t), srq->srq_srqnum,
sleepflag);
if (status != TAVOR_CMD_SUCCESS) {
cmn_err(CE_CONT, "Tavor: SW2HW_SRQ command failed: %08x\n",
status);
goto srqalloc_fail8;
}
srq->srq_srqcrsrcp = srqc;
srq->srq_rsrcp = rsrc;
srq->srq_mrhdl = mr;
srq->srq_refcnt = 0;
srq->srq_is_umap = srq_is_umap;
srq->srq_uarpg = (srq->srq_is_umap) ? uarpg : 0;
srq->srq_umap_dhp = (devmap_cookie_t)NULL;
srq->srq_pdhdl = pd;
srq->srq_wq_lastwqeindx = -1;
srq->srq_wq_bufsz = (1 << log_srq_size);
srq->srq_wq_buf = buf;
srq->srq_desc_off = srq_desc_off;
srq->srq_hdlrarg = (void *)ibt_srqhdl;
srq->srq_state = 0;
srq->srq_real_sizes.srq_wr_sz = (1 << log_srq_size);
srq->srq_real_sizes.srq_sgl_sz = srq->srq_wq_sgl;
srq->srq_sync = TAVOR_SRQ_IS_SYNC_REQ(state, srq->srq_wqinfo);
ASSERT(state->ts_srqhdl[srqc->tr_indx] == NULL);
state->ts_srqhdl[srqc->tr_indx] = srq;
if (srq->srq_is_umap) {
tavor_umap_db_add(umapdb);
} else {
mutex_enter(&srq->srq_wrid_wql->wql_lock);
tavor_wrid_list_srq_init(srq->srq_wridlist, srq, 0);
mutex_exit(&srq->srq_wrid_wql->wql_lock);
}
*srqhdl = srq;
return (status);
srqalloc_fail8:
kmem_free(srq->srq_wridlist->wl_wre, srq->srq_wridlist->wl_size *
sizeof (tavor_wrid_entry_t));
kmem_free(srq->srq_wridlist, sizeof (tavor_wrid_list_hdr_t));
srqalloc_fail7:
tavor_wql_refcnt_dec(srq->srq_wrid_wql);
srqalloc_fail6:
if (tavor_mr_deregister(state, &mr, TAVOR_MR_DEREG_ALL,
TAVOR_SLEEPFLAG_FOR_CONTEXT()) != DDI_SUCCESS) {
TAVOR_WARNING(state, "failed to deregister SRQ memory");
}
srqalloc_fail5:
tavor_queue_free(state, &srq->srq_wqinfo);
srqalloc_fail4:
if (srq_is_umap) {
tavor_umap_db_free(umapdb);
}
srqalloc_fail3:
tavor_rsrc_free(state, &rsrc);
srqalloc_fail2:
tavor_rsrc_free(state, &srqc);
srqalloc_fail1:
tavor_pd_refcnt_dec(pd);
return (status);
}
int
tavor_srq_free(tavor_state_t *state, tavor_srqhdl_t *srqhdl, uint_t sleepflag)
{
tavor_rsrc_t *srqc, *rsrc;
tavor_umap_db_entry_t *umapdb;
uint64_t value;
tavor_srqhdl_t srq;
tavor_mrhdl_t mr;
tavor_pdhdl_t pd;
tavor_hw_srqc_t srqc_entry;
uint32_t srqnum;
uint32_t size;
uint_t maxprot;
int status;
srq = *srqhdl;
mutex_enter(&srq->srq_lock);
srqc = srq->srq_srqcrsrcp;
rsrc = srq->srq_rsrcp;
pd = srq->srq_pdhdl;
mr = srq->srq_mrhdl;
srqnum = srq->srq_srqnum;
if (srq->srq_refcnt != 0) {
mutex_exit(&srq->srq_lock);
return (IBT_SRQ_IN_USE);
}
if (srq->srq_is_umap) {
status = tavor_umap_db_find(state->ts_instance, srq->srq_srqnum,
MLNX_UMAP_SRQMEM_RSRC, &value, TAVOR_UMAP_DB_REMOVE,
&umapdb);
if (status != DDI_SUCCESS) {
mutex_exit(&srq->srq_lock);
TAVOR_WARNING(state, "failed to find in database");
return (ibc_get_ci_failure(0));
}
tavor_umap_db_free(umapdb);
if (srq->srq_umap_dhp != NULL) {
maxprot = (PROT_READ | PROT_WRITE | PROT_USER);
status = devmap_devmem_remap(srq->srq_umap_dhp,
state->ts_dip, 0, 0, srq->srq_wqinfo.qa_size,
maxprot, DEVMAP_MAPPING_INVALID, NULL);
if (status != DDI_SUCCESS) {
mutex_exit(&srq->srq_lock);
TAVOR_WARNING(state, "failed in SRQ memory "
"devmap_devmem_remap()");
return (ibc_get_ci_failure(0));
}
srq->srq_umap_dhp = (devmap_cookie_t)NULL;
}
}
state->ts_srqhdl[srqc->tr_indx] = NULL;
mutex_exit(&srq->srq_lock);
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*srq));
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*srq->srq_wridlist));
status = tavor_cmn_ownership_cmd_post(state, HW2SW_SRQ, &srqc_entry,
sizeof (tavor_hw_srqc_t), srqnum, sleepflag);
if (status != TAVOR_CMD_SUCCESS) {
TAVOR_WARNING(state, "failed to reclaim SRQC ownership");
cmn_err(CE_CONT, "Tavor: HW2SW_SRQ command failed: %08x\n",
status);
return (IBT_FAILURE);
}
status = tavor_mr_deregister(state, &mr, TAVOR_MR_DEREG_ALL,
sleepflag);
if (status != DDI_SUCCESS) {
TAVOR_WARNING(state, "failed to deregister SRQ memory");
return (IBT_FAILURE);
}
if (srq->srq_wridlist != NULL) {
size = (srq->srq_wridlist->wl_size *
sizeof (tavor_wrid_entry_t));
kmem_free(srq->srq_wridlist->wl_wre, size);
kmem_free(srq->srq_wridlist, sizeof (tavor_wrid_list_hdr_t));
tavor_wql_refcnt_dec(srq->srq_wrid_wql);
}
tavor_queue_free(state, &srq->srq_wqinfo);
tavor_rsrc_free(state, &rsrc);
tavor_rsrc_free(state, &srqc);
tavor_pd_refcnt_dec(pd);
*srqhdl = NULL;
return (DDI_SUCCESS);
}
int
tavor_srq_modify(tavor_state_t *state, tavor_srqhdl_t srq, uint_t size,
uint_t *real_size, uint_t sleepflag)
{
tavor_qalloc_info_t new_srqinfo, old_srqinfo;
tavor_rsrc_t *mtt, *mpt, *old_mtt;
tavor_bind_info_t bind;
tavor_bind_info_t old_bind;
tavor_rsrc_pool_info_t *rsrc_pool;
tavor_mrhdl_t mr;
tavor_hw_mpt_t mpt_entry;
tavor_wrid_entry_t *wre_new, *wre_old;
uint64_t mtt_ddrbaseaddr, mtt_addr;
uint64_t srq_desc_off;
uint32_t *buf, srq_old_bufsz;
uint32_t wqesz;
uint_t max_srq_size;
uint_t dma_xfer_mode, mtt_pgsize_bits;
uint_t srq_sync, log_srq_size, maxprot;
uint_t wq_location;
int status;
wq_location = state->ts_cfg_profile->cp_srq_wq_inddr;
max_srq_size = (1 << state->ts_cfg_profile->cp_log_max_srq_sz);
if (size > max_srq_size) {
return (IBT_HCA_WR_EXCEEDED);
}
size = max(size, TAVOR_SRQ_MIN_SIZE);
log_srq_size = highbit(size);
if (ISP2(size)) {
log_srq_size = log_srq_size - 1;
}
if (log_srq_size > state->ts_cfg_profile->cp_log_max_srq_sz) {
goto srqmodify_fail;
}
wqesz = (1 << srq->srq_wq_log_wqesz);
new_srqinfo.qa_size = (1 << log_srq_size) * wqesz;
new_srqinfo.qa_alloc_align = PAGESIZE;
new_srqinfo.qa_bind_align = PAGESIZE;
if (srq->srq_is_umap) {
new_srqinfo.qa_location = TAVOR_QUEUE_LOCATION_USERLAND;
} else {
new_srqinfo.qa_location = wq_location;
}
status = tavor_queue_alloc(state, &new_srqinfo, sleepflag);
if (status != DDI_SUCCESS) {
goto srqmodify_fail;
}
buf = (uint32_t *)new_srqinfo.qa_buf_aligned;
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*buf))
wre_new = (tavor_wrid_entry_t *)kmem_zalloc((1 << log_srq_size) *
sizeof (tavor_wrid_entry_t), sleepflag);
if (wre_new == NULL) {
goto srqmodify_fail;
}
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(bind))
bzero(&bind, sizeof (tavor_bind_info_t));
bind.bi_type = TAVOR_BINDHDL_VADDR;
bind.bi_addr = (uint64_t)(uintptr_t)buf;
bind.bi_len = new_srqinfo.qa_size;
bind.bi_as = NULL;
bind.bi_flags = sleepflag == TAVOR_SLEEP ? IBT_MR_SLEEP :
IBT_MR_NOSLEEP | IBT_MR_ENABLE_LOCAL_WRITE;
if (srq->srq_is_umap) {
bind.bi_bypass = state->ts_cfg_profile->cp_iommu_bypass;
} else {
if (wq_location == TAVOR_QUEUE_LOCATION_NORMAL) {
bind.bi_bypass =
state->ts_cfg_profile->cp_iommu_bypass;
dma_xfer_mode =
state->ts_cfg_profile->cp_streaming_consistent;
if (dma_xfer_mode == DDI_DMA_STREAMING) {
bind.bi_flags |= IBT_MR_NONCOHERENT;
}
} else {
bind.bi_bypass = TAVOR_BINDMEM_BYPASS;
}
}
status = tavor_mr_mtt_bind(state, &bind, new_srqinfo.qa_dmahdl, &mtt,
&mtt_pgsize_bits);
if (status != DDI_SUCCESS) {
kmem_free(wre_new, srq->srq_wq_bufsz *
sizeof (tavor_wrid_entry_t));
tavor_queue_free(state, &new_srqinfo);
goto srqmodify_fail;
}
bind.bi_addr = bind.bi_addr & ((1 << mtt_pgsize_bits) - 1);
srq_desc_off = (uint64_t)(uintptr_t)new_srqinfo.qa_buf_aligned -
(uint64_t)bind.bi_addr;
rsrc_pool = &state->ts_rsrc_hdl[TAVOR_MTT];
mtt_ddrbaseaddr = (uint64_t)(uintptr_t)rsrc_pool->rsrc_ddr_offset;
bzero(&mpt_entry, sizeof (tavor_hw_mpt_t));
mpt_entry.reg_win_len = bind.bi_len;
mtt_addr = mtt_ddrbaseaddr + (mtt->tr_indx << TAVOR_MTT_SIZE_SHIFT);
mpt_entry.mttseg_addr_h = mtt_addr >> 32;
mpt_entry.mttseg_addr_l = mtt_addr >> 6;
mutex_enter(&srq->srq_lock);
srq_old_bufsz = srq->srq_wq_bufsz;
bcopy(srq->srq_wq_buf, buf, srq_old_bufsz * wqesz);
srq_sync = TAVOR_SRQ_IS_SYNC_REQ(state, srq->srq_wqinfo);
if (srq_sync) {
(void) ddi_dma_sync(bind.bi_dmahdl, 0,
new_srqinfo.qa_size, DDI_DMA_SYNC_FORDEV);
}
mr = srq->srq_mrhdl;
mutex_enter(&mr->mr_lock);
mpt = srq->srq_mrhdl->mr_mptrsrcp;
status = tavor_modify_mpt_cmd_post(state, &mpt_entry, mpt->tr_indx,
TAVOR_CMD_MODIFY_MPT_RESIZESRQ, sleepflag);
if (status != TAVOR_CMD_SUCCESS) {
cmn_err(CE_CONT, "Tavor: MODIFY_MPT command failed: %08x\n",
status);
(void) tavor_mr_mtt_unbind(state, &srq->srq_mrhdl->mr_bindinfo,
srq->srq_mrhdl->mr_mttrsrcp);
kmem_free(wre_new, srq->srq_wq_bufsz *
sizeof (tavor_wrid_entry_t));
tavor_queue_free(state, &new_srqinfo);
mutex_exit(&mr->mr_lock);
mutex_exit(&srq->srq_lock);
return (ibc_get_ci_failure(0));
}
old_srqinfo = srq->srq_wqinfo;
old_mtt = srq->srq_mrhdl->mr_mttrsrcp;
bcopy(&srq->srq_mrhdl->mr_bindinfo, &old_bind,
sizeof (tavor_bind_info_t));
srq->srq_wqinfo = new_srqinfo;
srq->srq_wq_buf = buf;
srq->srq_wq_bufsz = (1 << log_srq_size);
bcopy(&bind, &srq->srq_mrhdl->mr_bindinfo, sizeof (tavor_bind_info_t));
srq->srq_mrhdl->mr_mttrsrcp = mtt;
srq->srq_desc_off = srq_desc_off;
srq->srq_real_sizes.srq_wr_sz = (1 << log_srq_size);
mr->mr_logmttpgsz = mtt_pgsize_bits;
mutex_exit(&mr->mr_lock);
#ifdef __lock_lint
mutex_enter(&srq->srq_wrid_wql->wql_lock);
#else
if (srq->srq_wrid_wql != NULL) {
mutex_enter(&srq->srq_wrid_wql->wql_lock);
}
#endif
wre_old = NULL;
if (srq->srq_wridlist != NULL) {
wre_old = srq->srq_wridlist->wl_wre;
bcopy(wre_old, wre_new, srq_old_bufsz *
sizeof (tavor_wrid_entry_t));
srq->srq_wridlist->wl_wre = wre_new;
srq->srq_wridlist->wl_size = srq->srq_wq_bufsz;
if (!srq->srq_is_umap) {
tavor_wrid_list_srq_init(srq->srq_wridlist, srq,
srq_old_bufsz);
}
}
#ifdef __lock_lint
mutex_exit(&srq->srq_wrid_wql->wql_lock);
#else
if (srq->srq_wrid_wql != NULL) {
mutex_exit(&srq->srq_wrid_wql->wql_lock);
}
#endif
if ((srq->srq_is_umap) && (srq->srq_umap_dhp != NULL)) {
maxprot = (PROT_READ | PROT_WRITE | PROT_USER);
status = devmap_devmem_remap(srq->srq_umap_dhp,
state->ts_dip, 0, 0, srq->srq_wqinfo.qa_size, maxprot,
DEVMAP_MAPPING_INVALID, NULL);
if (status != DDI_SUCCESS) {
mutex_exit(&srq->srq_lock);
TAVOR_WARNING(state, "failed in SRQ memory "
"devmap_devmem_remap()");
if (wre_old != NULL) {
kmem_free(wre_old, srq_old_bufsz *
sizeof (tavor_wrid_entry_t));
}
return (ibc_get_ci_failure(0));
}
srq->srq_umap_dhp = (devmap_cookie_t)NULL;
}
mutex_exit(&srq->srq_lock);
status = tavor_mr_mtt_unbind(state, &old_bind, old_mtt);
if (status != DDI_SUCCESS) {
TAVOR_WARNING(state, "failed to unbind old SRQ memory");
goto srqmodify_fail;
}
if (wre_old != NULL) {
kmem_free(wre_old, srq_old_bufsz *
sizeof (tavor_wrid_entry_t));
}
tavor_queue_free(state, &old_srqinfo);
if (real_size != NULL) {
*real_size = (1 << log_srq_size);
}
return (DDI_SUCCESS);
srqmodify_fail:
return (status);
}
void
tavor_srq_refcnt_inc(tavor_srqhdl_t srq)
{
mutex_enter(&srq->srq_lock);
srq->srq_refcnt++;
mutex_exit(&srq->srq_lock);
}
void
tavor_srq_refcnt_dec(tavor_srqhdl_t srq)
{
mutex_enter(&srq->srq_lock);
srq->srq_refcnt--;
mutex_exit(&srq->srq_lock);
}
tavor_srqhdl_t
tavor_srqhdl_from_srqnum(tavor_state_t *state, uint_t srqnum)
{
uint_t srqindx, srqmask;
srqmask = (1 << state->ts_cfg_profile->cp_log_num_srq) - 1;
srqindx = srqnum & srqmask;
return (state->ts_srqhdl[srqindx]);
}
static void
tavor_srq_sgl_to_logwqesz(tavor_state_t *state, uint_t num_sgl,
tavor_qp_wq_type_t wq_type, uint_t *logwqesz, uint_t *max_sgl)
{
uint_t max_size, log2, actual_sgl;
switch (wq_type) {
case TAVOR_QP_WQ_TYPE_RECVQ:
max_size = (TAVOR_QP_WQE_MLX_RCV_HDRS + (num_sgl << 4));
log2 = highbit(max_size);
if (ISP2(max_size)) {
log2 = log2 - 1;
}
log2 = max(log2, TAVOR_QP_WQE_LOG_MINIMUM);
actual_sgl = ((1 << log2) - TAVOR_QP_WQE_MLX_RCV_HDRS) >> 4;
break;
default:
TAVOR_WARNING(state, "unexpected work queue type");
break;
}
*logwqesz = log2;
*max_sgl = min(state->ts_cfg_profile->cp_srq_max_sgl, actual_sgl);
}