#include "dapl.h"
#include "dapl_tavor_wr.h"
#include "dapl_hash.h"
#include "dapl_tavor_ibtf_impl.h"
static dapls_tavor_wrid_entry_t *dapli_tavor_wrid_find_match(
dapls_tavor_workq_hdr_t *, tavor_hw_cqe_t *);
static dapls_tavor_wrid_list_hdr_t *dapli_tavor_wrid_get_list(uint32_t, int);
static void dapli_tavor_wrid_reaplist_add(ib_cq_handle_t,
dapls_tavor_workq_hdr_t *);
static dapls_tavor_workq_hdr_t *dapli_tavor_wrid_wqhdr_find(ib_cq_handle_t,
uint_t, uint_t);
static uint32_t dapli_tavor_wrid_get_wqeaddrsz(dapls_tavor_workq_hdr_t *);
static dapls_tavor_workq_hdr_t *dapli_tavor_wrid_list_reap(
dapls_tavor_wrid_list_hdr_t *);
static dapls_tavor_workq_hdr_t *dapli_tavor_wrid_wqhdr_create(ib_cq_handle_t,
uint_t, uint_t, uint_t);
static void dapli_tavor_wrid_wqhdr_add(dapls_tavor_workq_hdr_t *,
dapls_tavor_wrid_list_hdr_t *);
static void dapli_tavor_wrid_wqhdr_remove(dapls_tavor_workq_hdr_t *,
dapls_tavor_wrid_list_hdr_t *);
static void dapli_tavor_wrid_wqhdr_lock_both(ib_qp_handle_t);
static void dapli_tavor_wrid_wqhdr_unlock_both(ib_qp_handle_t);
static DAT_RETURN dapli_tavor_cq_wqhdr_add(ib_cq_handle_t,
dapls_tavor_workq_hdr_t *);
static void dapli_tavor_cq_wqhdr_remove(ib_cq_handle_t,
dapls_tavor_workq_hdr_t *);
uint64_t
dapls_tavor_wrid_get_entry(ib_cq_handle_t cq, tavor_hw_cqe_t *cqe,
uint_t send_or_recv, uint_t error, dapls_tavor_wrid_entry_t *wre)
{
dapls_tavor_workq_hdr_t *wq;
dapls_tavor_wrid_entry_t *wre_tmp;
uint64_t wrid;
uint_t qpnum;
dapl_os_lock(&cq->cq_wrid_wqhdr_lock);
qpnum = TAVOR_CQE_QPNUM_GET(cqe);
wq = dapli_tavor_wrid_wqhdr_find(cq, qpnum, send_or_recv);
dapl_os_assert(wq != NULL);
dapl_os_lock(&wq->wq_wrid_lock->wrl_lock);
wre_tmp = dapli_tavor_wrid_find_match(wq, cqe);
dapl_os_assert(error || (wre_tmp->wr_signaled_dbd &
TAVOR_WRID_ENTRY_SIGNALED));
if (error && (wre != NULL)) {
*wre = *wre_tmp;
wre->wr_wqeaddrsz = dapli_tavor_wrid_get_wqeaddrsz(wq);
}
wrid = wre_tmp->wr_wrid;
dapl_os_unlock(&wq->wq_wrid_lock->wrl_lock);
dapl_os_unlock(&cq->cq_wrid_wqhdr_lock);
return (wrid);
}
static dapls_tavor_wrid_entry_t *
dapli_tavor_wrid_find_match(dapls_tavor_workq_hdr_t *wq, tavor_hw_cqe_t *cqe)
{
dapls_tavor_wrid_entry_t *curr = NULL;
dapls_tavor_wrid_list_hdr_t *container;
uint32_t wqeaddr_size;
uint32_t head, tail, size;
int found = 0, last_container;
wqeaddr_size = TAVOR_CQE_WQEADDRSZ_GET(cqe);
container = wq->wq_wrid_poll;
while (container != NULL) {
last_container = (container != wq->wq_wrid_post) ? 0 : 1;
if (container->wl_srq_en) {
dapl_os_assert(last_container == 1);
curr = dapli_tavor_wrid_find_match_srq(container, cqe);
break;
}
head = container->wl_head;
tail = container->wl_tail;
size = container->wl_size;
while ((head != tail) || (container->wl_full)) {
container->wl_full = 0;
curr = &container->wl_wre[head];
head = ((head + 1) & (size - 1));
if (curr->wr_wqeaddrsz == wqeaddr_size) {
found = 1;
break;
}
}
if (head == tail) {
container->wl_wre_old_tail = NULL;
if (!last_container) {
wq->wq_wrid_poll = container->wl_next;
}
}
container->wl_head = head;
if (found) {
break;
} else {
curr = NULL;
container = container->wl_next;
}
}
if (last_container) {
wq->wq_head = wq->wq_wrid_post->wl_head;
wq->wq_full = wq->wq_wrid_post->wl_full;
}
dapl_os_assert(curr != NULL);
return (curr);
}
dapls_tavor_wrid_entry_t *
dapli_tavor_wrid_find_match_srq(dapls_tavor_wrid_list_hdr_t *wl,
tavor_hw_cqe_t *cqe)
{
dapls_tavor_wrid_entry_t *wre;
uint32_t wqe_index;
uint32_t wqe_addr;
uint32_t qsize_msk;
uint32_t tail, next_tail;
wqe_addr = TAVOR_CQE_WQEADDRSZ_GET(cqe) & 0xFFFFFFC0;
wqe_index = TAVOR_SRQ_WQ_INDEX(wl->wl_srq_desc_addr, wqe_addr,
wl->wl_srq_wqesz);
dapl_os_assert(wqe_index < wl->wl_size);
qsize_msk = wl->wl_size - 1;
tail = wl->wl_freel_tail;
next_tail = (tail + 1) & qsize_msk;
wl->wl_freel_entries++;
dapl_os_assert(wl->wl_freel_entries <= wl->wl_size);
wl->wl_free_list[tail] = wqe_addr;
wl->wl_freel_tail = next_tail;
wre = &wl->wl_wre[wqe_index];
return (wre);
}
void
dapls_tavor_wrid_cq_reap(ib_cq_handle_t cq)
{
dapls_tavor_workq_hdr_t *consume_wqhdr;
dapls_tavor_wrid_list_hdr_t *container, *to_free;
dapl_os_lock(&cq->cq_wrid_wqhdr_lock);
container = cq->cq_wrid_reap_head;
while (container != NULL) {
to_free = container;
container = container->wl_reap_next;
consume_wqhdr = dapli_tavor_wrid_list_reap(to_free);
if (consume_wqhdr != NULL) {
dapli_tavor_cq_wqhdr_remove(cq, consume_wqhdr);
}
}
cq->cq_wrid_reap_head = cq->cq_wrid_reap_tail = NULL;
dapl_os_unlock(&cq->cq_wrid_wqhdr_lock);
}
void
dapls_tavor_wrid_cq_force_reap(ib_cq_handle_t cq)
{
DAPL_HASH_DATA curr;
DAT_RETURN retval;
dapls_tavor_workq_hdr_t *to_free_wqhdr;
dapls_tavor_wrid_list_hdr_t *container, *to_free;
dapls_tavor_wrid_cq_reap(cq);
dapl_os_lock(&cq->cq_wrid_wqhdr_lock);
retval = dapls_hash_iterate(cq->cq_wrid_wqhdr_list,
DAPL_HASH_ITERATE_INIT, &curr);
dapl_os_assert(retval == DAT_SUCCESS);
while (curr != NULL) {
to_free_wqhdr = (dapls_tavor_workq_hdr_t *)curr;
container = ((dapls_tavor_workq_hdr_t *)curr)->wq_wrid_poll;
retval = dapls_hash_iterate(cq->cq_wrid_wqhdr_list,
DAPL_HASH_ITERATE_NEXT, &curr);
dapl_os_assert(retval == DAT_SUCCESS);
while (container != NULL) {
to_free = container;
container = container->wl_next;
(void) dapli_tavor_wrid_list_reap(to_free);
if (container == NULL) {
dapli_tavor_cq_wqhdr_remove(cq, to_free_wqhdr);
}
}
}
dapl_os_lock(&cq->cq_wrid_wqhdr_lock);
}
static dapls_tavor_wrid_list_hdr_t *
dapli_tavor_wrid_get_list(uint32_t qsize, int wrid_for_srq)
{
dapls_tavor_wrid_list_hdr_t *wridlist;
dapls_tavor_wrid_entry_t *wl_wre;
uint32_t *wl_freel;
uint32_t size;
uint32_t wl_wre_size;
uint32_t wl_freel_size;
wridlist = NULL;
wl_wre = NULL;
wl_freel = NULL;
size = wl_wre_size = wl_freel_size = 0;
size = sizeof (dapls_tavor_wrid_list_hdr_t);
if (wrid_for_srq) {
size = size + sizeof (dapls_tavor_wrid_lock_t);
}
wridlist = dapl_os_alloc(size);
if (wridlist == NULL) {
goto bail;
}
if (wrid_for_srq) {
wridlist->wl_lock = (dapls_tavor_wrid_lock_t *)(
(uintptr_t)wridlist + sizeof (dapls_tavor_wrid_list_hdr_t));
dapl_os_lock_init(&wridlist->wl_lock->wrl_lock);
wridlist->wl_lock->wrl_on_srq = wrid_for_srq;
} else {
wridlist->wl_lock = NULL;
}
wl_wre_size = qsize * sizeof (dapls_tavor_wrid_entry_t);
wl_wre = dapl_os_alloc(wl_wre_size);
if (wl_wre == NULL) {
goto bail;
}
if (wrid_for_srq) {
wl_freel_size = qsize * sizeof (uint32_t);
wl_freel = dapl_os_alloc(wl_freel_size);
if (wl_freel == NULL) {
goto bail;
}
}
wridlist->wl_size = qsize;
wridlist->wl_full = 0;
wridlist->wl_head = 0;
wridlist->wl_tail = 0;
wridlist->wl_wre = wl_wre;
wridlist->wl_wre_old_tail = NULL;
wridlist->wl_reap_next = NULL;
wridlist->wl_next = NULL;
wridlist->wl_prev = NULL;
if (wrid_for_srq) {
wridlist->wl_srq_en = 1;
wridlist->wl_free_list = (uint32_t *)wl_freel;
wridlist->wl_freel_head = 0;
wridlist->wl_freel_tail = 0;
wridlist->wl_freel_entries = qsize;
} else {
wridlist->wl_srq_en = 0;
wridlist->wl_free_list = NULL;
wridlist->wl_freel_head = 0;
wridlist->wl_freel_tail = 0;
wridlist->wl_freel_entries = 0;
wridlist->wl_srq_wqesz = 0;
wridlist->wl_srq_desc_addr = 0;
}
return (wridlist);
bail:
if (wridlist) {
if (wrid_for_srq) {
dapl_os_lock_destroy(&wridlist->wl_lock->wrl_lock);
}
dapl_os_free(wridlist, size);
}
if (wl_wre) {
dapl_os_free(wl_wre, wl_wre_size);
}
if (wl_freel) {
dapl_os_free(wl_freel, wl_freel_size);
}
return (NULL);
}
static void
dapli_tavor_wrid_reaplist_add(ib_cq_handle_t cq, dapls_tavor_workq_hdr_t *wq)
{
dapl_os_lock(&wq->wq_wrid_lock->wrl_lock);
if ((cq->cq_wrid_reap_head == NULL) &&
(cq->cq_wrid_reap_tail == NULL)) {
cq->cq_wrid_reap_head = wq->wq_wrid_post;
cq->cq_wrid_reap_tail = wq->wq_wrid_post;
} else {
cq->cq_wrid_reap_tail->wl_reap_next = wq->wq_wrid_post;
cq->cq_wrid_reap_tail = wq->wq_wrid_post;
}
dapl_os_unlock(&wq->wq_wrid_lock->wrl_lock);
}
static dapls_tavor_workq_hdr_t *
dapli_tavor_wrid_wqhdr_find(ib_cq_handle_t cq, uint_t qpn, uint_t send_or_recv)
{
DAPL_HASH_DATA curr;
DAPL_HASH_KEY key;
DAT_RETURN status;
key = (DAPL_HASH_KEY)(((uint64_t)send_or_recv << 32) | (uint32_t)qpn);
status = dapls_hash_search(cq->cq_wrid_wqhdr_list, key, &curr);
if (status == DAT_SUCCESS) {
return ((dapls_tavor_workq_hdr_t *)curr);
} else {
return (NULL);
}
}
static uint32_t
dapli_tavor_wrid_get_wqeaddrsz(dapls_tavor_workq_hdr_t *wq)
{
dapls_tavor_wrid_entry_t *wre;
uint32_t wqeaddrsz;
uint32_t head;
if (wq->wq_wrid_poll->wl_head == wq->wq_wrid_poll->wl_tail) {
wqeaddrsz = 0;
} else {
head = wq->wq_wrid_poll->wl_head;
wre = &wq->wq_wrid_poll->wl_wre[head];
wqeaddrsz = wre->wr_wqeaddrsz;
}
return (wqeaddrsz);
}
static dapls_tavor_workq_hdr_t *
dapli_tavor_wrid_list_reap(dapls_tavor_wrid_list_hdr_t *wridlist)
{
dapls_tavor_workq_hdr_t *wqhdr, *consume_wqhdr = NULL;
dapls_tavor_wrid_list_hdr_t *prev, *next;
wqhdr = wridlist->wl_wqhdr;
dapl_os_lock(&wqhdr->wq_wrid_lock->wrl_lock);
prev = wridlist->wl_prev;
next = wridlist->wl_next;
if (prev != NULL) {
prev->wl_next = next;
}
if (next != NULL) {
next->wl_prev = prev;
}
if ((wqhdr->wq_wrid_poll == wridlist) &&
(wqhdr->wq_wrid_post == wridlist)) {
consume_wqhdr = wqhdr;
}
if (wqhdr->wq_wrid_poll == wridlist) {
wqhdr->wq_wrid_poll = next;
}
if (wqhdr->wq_wrid_post == wridlist) {
wqhdr->wq_wrid_post = NULL;
}
if (!wridlist->wl_srq_en) {
if (wridlist->wl_wre) {
dapl_os_free(wridlist->wl_wre, wridlist->wl_size *
sizeof (dapls_tavor_wrid_entry_t));
}
dapl_os_assert(wridlist->wl_free_list == NULL);
dapl_os_free(wridlist, sizeof (dapls_tavor_wrid_list_hdr_t));
}
dapl_os_unlock(&wqhdr->wq_wrid_lock->wrl_lock);
return (consume_wqhdr);
}
DAT_RETURN
dapls_tavor_srq_wrid_init(ib_srq_handle_t srq)
{
dapls_tavor_wrid_list_hdr_t *wridlist;
int i;
wridlist = dapli_tavor_wrid_get_list(srq->srq_wq_numwqe, 1);
if (wridlist == NULL) {
srq->srq_wridlist = NULL;
return (DAT_INSUFFICIENT_RESOURCES | DAT_RESOURCE_MEMORY);
}
wridlist->wl_free_list[0] = srq->srq_wq_desc_addr;
for (i = 1; i < srq->srq_wq_numwqe; i++) {
wridlist->wl_free_list[i] = wridlist->wl_free_list[i-1] +
srq->srq_wq_wqesz;
}
wridlist->wl_srq_wqesz = srq->srq_wq_wqesz;
wridlist->wl_srq_desc_addr = srq->srq_wq_desc_addr;
srq->srq_wridlist = wridlist;
return (DAT_SUCCESS);
}
void
dapls_tavor_srq_wrid_free(ib_srq_handle_t srq)
{
dapls_tavor_wrid_list_hdr_t *wridlist;
size_t size = 0;
wridlist = srq->srq_wridlist;
if (wridlist) {
dapl_os_assert(wridlist->wl_srq_en == 1);
if (wridlist->wl_wre) {
dapl_os_free(wridlist->wl_wre, wridlist->wl_size *
sizeof (dapls_tavor_wrid_entry_t));
}
if (wridlist->wl_free_list) {
dapl_os_free(wridlist->wl_free_list, wridlist->wl_size *
sizeof (uint32_t));
}
if (wridlist->wl_lock) {
dapl_os_assert(wridlist->wl_lock->wrl_on_srq == 1);
dapl_os_lock_destroy(&wridlist->wl_lock->wrl_lock);
size = sizeof (dapls_tavor_wrid_lock_t);
}
size = size;
dapl_os_free(wridlist, size +
sizeof (dapls_tavor_wrid_list_hdr_t));
srq->srq_wridlist = NULL;
}
}
DAT_RETURN
dapls_tavor_wrid_init(ib_qp_handle_t qp)
{
dapls_tavor_workq_hdr_t *swq;
dapls_tavor_workq_hdr_t *rwq;
dapls_tavor_wrid_list_hdr_t *s_wridlist;
dapls_tavor_wrid_list_hdr_t *r_wridlist;
uint_t create_new_swq = 0;
uint_t create_new_rwq = 0;
dapli_tavor_wrid_wqhdr_lock_both(qp);
swq = dapli_tavor_wrid_wqhdr_find(qp->qp_sq_cqhdl, qp->qp_num,
TAVOR_WR_SEND);
if (swq == NULL) {
create_new_swq = 1;
swq = dapli_tavor_wrid_wqhdr_create(qp->qp_sq_cqhdl,
qp->qp_num, TAVOR_WR_SEND, 1);
if (swq == NULL) {
dapli_tavor_wrid_wqhdr_unlock_both(qp);
return (DAT_INSUFFICIENT_RESOURCES);
}
}
qp->qp_sq_wqhdr = swq;
swq->wq_size = qp->qp_sq_numwqe;
swq->wq_head = 0;
swq->wq_tail = 0;
swq->wq_full = 0;
s_wridlist = dapli_tavor_wrid_get_list(swq->wq_size, 0);
if (s_wridlist == NULL) {
if (create_new_swq) {
dapli_tavor_cq_wqhdr_remove(qp->qp_sq_cqhdl, swq);
}
dapli_tavor_wrid_wqhdr_unlock_both(qp);
return (DAT_INSUFFICIENT_RESOURCES | DAT_RESOURCE_MEMORY);
}
s_wridlist->wl_wqhdr = swq;
dapl_os_lock(&swq->wq_wrid_lock->wrl_lock);
dapli_tavor_wrid_wqhdr_add(swq, s_wridlist);
dapl_os_unlock(&swq->wq_wrid_lock->wrl_lock);
rwq = dapli_tavor_wrid_wqhdr_find(qp->qp_rq_cqhdl, qp->qp_num,
TAVOR_WR_RECV);
if (rwq == NULL) {
create_new_rwq = 1;
rwq = dapli_tavor_wrid_wqhdr_create(qp->qp_rq_cqhdl,
qp->qp_num, TAVOR_WR_RECV, qp->qp_srq_enabled ? 0 : 1);
if (rwq == NULL) {
dapl_os_lock(&swq->wq_wrid_lock->wrl_lock);
dapli_tavor_wrid_wqhdr_remove(swq, s_wridlist);
dapl_os_unlock(&swq->wq_wrid_lock->wrl_lock);
if (create_new_swq) {
dapli_tavor_cq_wqhdr_remove(qp->qp_sq_cqhdl,
swq);
}
dapli_tavor_wrid_wqhdr_unlock_both(qp);
return (DAT_INSUFFICIENT_RESOURCES |
DAT_RESOURCE_MEMORY);
}
}
qp->qp_rq_wqhdr = rwq;
rwq->wq_size = qp->qp_rq_numwqe;
rwq->wq_head = 0;
rwq->wq_tail = 0;
rwq->wq_full = 0;
if (qp->qp_srq_enabled) {
r_wridlist = qp->qp_srq->srq_wridlist;
dapl_os_assert(r_wridlist != NULL);
rwq->wq_wrid_lock = r_wridlist->wl_lock;
dapl_os_assert(rwq->wq_wrid_lock != NULL);
} else {
r_wridlist = dapli_tavor_wrid_get_list(rwq->wq_size, 0);
}
if (r_wridlist == NULL) {
dapl_os_lock(&swq->wq_wrid_lock->wrl_lock);
dapli_tavor_wrid_wqhdr_remove(swq, s_wridlist);
dapl_os_unlock(&swq->wq_wrid_lock->wrl_lock);
if (create_new_swq) {
dapli_tavor_cq_wqhdr_remove(qp->qp_sq_cqhdl, swq);
}
if (create_new_rwq) {
dapli_tavor_cq_wqhdr_remove(qp->qp_rq_cqhdl, rwq);
}
dapli_tavor_wrid_wqhdr_unlock_both(qp);
return (DAT_INSUFFICIENT_RESOURCES | DAT_RESOURCE_MEMORY);
}
if (!qp->qp_srq_enabled) {
r_wridlist->wl_wqhdr = rwq;
}
dapl_os_lock(&rwq->wq_wrid_lock->wrl_lock);
dapli_tavor_wrid_wqhdr_add(rwq, r_wridlist);
dapl_os_unlock(&rwq->wq_wrid_lock->wrl_lock);
dapli_tavor_wrid_wqhdr_unlock_both(qp);
return (DAT_SUCCESS);
}
void
dapls_tavor_wrid_cleanup(DAPL_EP *ep, ib_qp_handle_t qp)
{
dapli_tavor_wrid_wqhdr_lock_both(qp);
dapli_tavor_wrid_reaplist_add(qp->qp_sq_cqhdl, qp->qp_sq_wqhdr);
if (qp->qp_srq_enabled) {
dapl_os_lock(&qp->qp_rq_wqhdr->wq_wrid_lock->wrl_lock);
DAPL_FLUSH(ep)(qp);
dapli_tavor_wrid_wqhdr_remove(qp->qp_rq_wqhdr,
qp->qp_rq_wqhdr->wq_wrid_post);
dapl_os_assert(qp->qp_rq_wqhdr->wq_wrid_post == NULL);
dapl_os_unlock(&qp->qp_rq_wqhdr->wq_wrid_lock->wrl_lock);
dapli_tavor_cq_wqhdr_remove(qp->qp_rq_cqhdl, qp->qp_rq_wqhdr);
} else {
dapli_tavor_wrid_reaplist_add(qp->qp_rq_cqhdl, qp->qp_rq_wqhdr);
}
dapli_tavor_wrid_wqhdr_unlock_both(qp);
}
static dapls_tavor_workq_hdr_t *
dapli_tavor_wrid_wqhdr_create(ib_cq_handle_t cq, uint_t qpn,
uint_t send_or_recv, uint_t alloc_wrl)
{
dapls_tavor_workq_hdr_t *wqhdr_tmp;
size_t size, aligned_size;
size = (sizeof (dapls_tavor_workq_hdr_t) + 0x7) & ~0x7;
aligned_size = size;
if (alloc_wrl) {
size = size + sizeof (dapls_tavor_wrid_lock_t);
}
wqhdr_tmp = dapl_os_alloc(size);
if (wqhdr_tmp == NULL) {
return (NULL);
}
if (alloc_wrl) {
wqhdr_tmp->wq_wrid_lock = (dapls_tavor_wrid_lock_t *)
(((uintptr_t)wqhdr_tmp + aligned_size) & ~0x7);
dapl_os_lock_init(&wqhdr_tmp->wq_wrid_lock->wrl_lock);
wqhdr_tmp->wq_wrid_lock->wrl_on_srq = 0;
}
wqhdr_tmp->wq_qpn = qpn;
wqhdr_tmp->wq_send_or_recv = send_or_recv;
wqhdr_tmp->wq_wrid_poll = NULL;
wqhdr_tmp->wq_wrid_post = NULL;
if (dapli_tavor_cq_wqhdr_add(cq, wqhdr_tmp) != DAT_SUCCESS) {
if (alloc_wrl) {
dapl_os_lock_destroy(&wqhdr_tmp->wq_wrid_lock->
wrl_lock);
}
dapl_os_free(wqhdr_tmp, size);
wqhdr_tmp = NULL;
}
return (wqhdr_tmp);
}
static void
dapli_tavor_wrid_wqhdr_add(dapls_tavor_workq_hdr_t *wqhdr,
dapls_tavor_wrid_list_hdr_t *wridlist)
{
if ((wqhdr->wq_wrid_post == NULL) &&
(wqhdr->wq_wrid_poll == NULL)) {
wqhdr->wq_wrid_poll = wridlist;
wqhdr->wq_wrid_post = wridlist;
} else {
wqhdr->wq_wrid_post->wl_next = wridlist;
wridlist->wl_prev = wqhdr->wq_wrid_post;
wqhdr->wq_wrid_post = wridlist;
}
}
static void
dapli_tavor_wrid_wqhdr_remove(dapls_tavor_workq_hdr_t *wqhdr,
dapls_tavor_wrid_list_hdr_t *wridlist)
{
dapls_tavor_wrid_list_hdr_t *prev, *next;
prev = wridlist->wl_prev;
next = wridlist->wl_next;
if (prev != NULL) {
prev->wl_next = next;
}
if (next != NULL) {
next->wl_prev = prev;
}
if (wqhdr->wq_wrid_post == wridlist) {
wqhdr->wq_wrid_post = prev;
}
if (wqhdr->wq_wrid_poll == wridlist) {
wqhdr->wq_wrid_poll = NULL;
}
}
static void
dapli_tavor_wrid_wqhdr_lock_both(ib_qp_handle_t qp)
{
ib_cq_handle_t sq_cq, rq_cq;
sq_cq = qp->qp_sq_cqhdl;
rq_cq = qp->qp_rq_cqhdl;
if (sq_cq == rq_cq) {
dapl_os_lock(&sq_cq->cq_wrid_wqhdr_lock);
} else {
dapl_os_lock(&sq_cq->cq_wrid_wqhdr_lock);
dapl_os_lock(&rq_cq->cq_wrid_wqhdr_lock);
}
}
static void
dapli_tavor_wrid_wqhdr_unlock_both(ib_qp_handle_t qp)
{
ib_cq_handle_t sq_cq, rq_cq;
sq_cq = qp->qp_sq_cqhdl;
rq_cq = qp->qp_rq_cqhdl;
if (sq_cq == rq_cq) {
dapl_os_unlock(&sq_cq->cq_wrid_wqhdr_lock);
} else {
dapl_os_unlock(&rq_cq->cq_wrid_wqhdr_lock);
dapl_os_unlock(&sq_cq->cq_wrid_wqhdr_lock);
}
}
static DAT_RETURN
dapli_tavor_cq_wqhdr_add(ib_cq_handle_t cq, dapls_tavor_workq_hdr_t *wqhdr)
{
DAPL_HASH_KEY key;
key = (DAPL_HASH_KEY)(((uint64_t)wqhdr->wq_send_or_recv << 32) |
wqhdr->wq_qpn);
return (dapls_hash_insert(cq->cq_wrid_wqhdr_list, key, wqhdr));
}
static void
dapli_tavor_cq_wqhdr_remove(ib_cq_handle_t cq, dapls_tavor_workq_hdr_t *wqhdr)
{
DAPL_HASH_DATA curr;
DAPL_HASH_KEY key;
size_t size = 0;
key = (DAPL_HASH_KEY)(((uint64_t)wqhdr->wq_send_or_recv << 32) |
wqhdr->wq_qpn);
(void) dapls_hash_remove(cq->cq_wrid_wqhdr_list, key, &curr);
size = (sizeof (dapls_tavor_workq_hdr_t) + 0x7) & ~0x7;
if (wqhdr->wq_wrid_lock && (!wqhdr->wq_wrid_lock->wrl_on_srq)) {
dapl_os_lock_destroy(&wqhdr->wq_wrid_lock->wrl_lock);
size += sizeof (dapls_tavor_wrid_lock_t);
}
dapl_os_free(wqhdr, size);
}
DAT_BOOLEAN
dapls_tavor_srq_wrid_resize(ib_srq_handle_t srq_handle, uint32_t new_size)
{
dapls_tavor_wrid_list_hdr_t *wridlist;
dapls_tavor_wrid_entry_t *old_wl_wre;
dapls_tavor_wrid_entry_t *new_wl_wre;
uint32_t *old_wl_freel;
uint32_t *new_wl_freel;
uint32_t old_size;
uint32_t idx;
uint32_t prev_idx;
uint32_t i;
wridlist = srq_handle->srq_wridlist;
if (wridlist == NULL) {
return (DAT_FALSE);
}
dapl_os_assert(wridlist->wl_srq_en);
dapl_os_lock(&wridlist->wl_lock->wrl_lock);
old_wl_wre = wridlist->wl_wre;
old_wl_freel = wridlist->wl_free_list;
old_size = wridlist->wl_size;
new_wl_wre = (dapls_tavor_wrid_entry_t *)dapl_os_alloc(new_size *
sizeof (dapls_tavor_wrid_entry_t));
if (new_wl_wre == NULL) {
goto bail;
}
new_wl_freel = dapl_os_alloc(new_size * sizeof (uint32_t));
if (new_wl_freel == NULL) {
goto bail;
}
(void) dapl_os_memcpy(&new_wl_wre[0], &old_wl_wre[0],
old_size * sizeof (dapls_tavor_wrid_entry_t));
idx = wridlist->wl_freel_head;
for (i = 0; i < wridlist->wl_freel_entries; i++) {
new_wl_freel[i] = old_wl_freel[idx];
idx = (idx + 1) % old_size;
}
idx = wridlist->wl_freel_entries;
new_wl_freel[idx] = wridlist->wl_srq_desc_addr + old_size *
wridlist->wl_srq_wqesz;
prev_idx = idx;
idx = (idx + 1) % new_size;
for (i = 0; i < new_size - old_size - 1; i++) {
new_wl_freel[idx] = new_wl_freel[prev_idx] +
wridlist->wl_srq_wqesz;
prev_idx = idx;
idx = (idx + 1) % new_size;
}
wridlist->wl_size = new_size;
wridlist->wl_wre = new_wl_wre;
wridlist->wl_free_list = new_wl_freel;
wridlist->wl_freel_head = 0;
wridlist->wl_freel_tail = idx;
wridlist->wl_freel_entries = wridlist->wl_freel_entries + new_size -
old_size;
dapl_os_unlock(&wridlist->wl_lock->wrl_lock);
if (old_wl_wre) {
dapl_os_free(old_wl_wre, old_size *
sizeof (dapls_tavor_wrid_entry_t));
}
if (old_wl_freel) {
dapl_os_free(old_wl_freel, old_size * sizeof (uint32_t));
}
return (DAT_TRUE);
bail:
dapl_os_unlock(&wridlist->wl_lock->wrl_lock);
if (new_wl_wre) {
dapl_os_free(new_wl_wre, new_size *
sizeof (dapls_tavor_wrid_entry_t));
}
return (DAT_FALSE);
}