root/usr/src/lib/udapl/udapl_tavor/tavor/dapl_tavor_ibtf_qp.c
/*
 * 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
 * or http://www.opensolaris.org/os/licensing.
 * 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 2010 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#include "dapl.h"
#include "dapl_adapter_util.h"
#include "dapl_evd_util.h"
#include "dapl_cr_util.h"
#include "dapl_lmr_util.h"
#include "dapl_rmr_util.h"
#include "dapl_cookie.h"
#include "dapl_tavor_ibtf_impl.h"
#include "dapl_hash.h"

/* Function prototypes */
extern DAT_RETURN dapls_tavor_wrid_init(ib_qp_handle_t);
extern DAT_RETURN dapls_tavor_srq_wrid_init(ib_srq_handle_t);
extern void dapls_tavor_srq_wrid_free(ib_srq_handle_t);
extern DAT_BOOLEAN dapls_tavor_srq_wrid_resize(ib_srq_handle_t, uint32_t);

static DAT_RETURN dapli_ib_srq_add_ep(IN ib_srq_handle_t srq_ptr,
    IN uint32_t qpnum, IN DAPL_EP *ep_ptr);
static void dapli_ib_srq_remove_ep(IN ib_srq_handle_t srq_ptr,
    IN uint32_t qpnum);
static DAT_RETURN dapli_ib_srq_resize_internal(IN DAPL_SRQ *srq_ptr,
    IN DAT_COUNT srqlen);
/*
 * dapli_get_dto_cq
 *
 * Obtain the cq_handle for a DTO EVD. If the EVD is NULL, use the
 * null_ib_cq_handle. If it hasn't been created yet, create it now in
 * the HCA structure. It will be cleaned up in dapls_ib_cqd_destroy().
 *
 * This is strictly internal to IB. DAPL allows a NULL DTO EVD handle,
 * but IB does not. So we create a CQ under the hood and make sure
 * an error is generated if the user every tries to post, by
 * setting the WQ length to 0 in ep_create and/or ep_modify.
 *
 * Returns
 *      A valid CQ handle
 */
static ib_cq_handle_t
dapli_get_dto_cq(
        IN  DAPL_IA     *ia_ptr,
        IN  DAPL_EVD    *evd_ptr)
{
        dapl_evd_create_t       create_msg;
        ib_cq_handle_t          cq_handle;
        int                     ia_fd;
        int                     retval;
        mlnx_umap_cq_data_out_t *mcq;

        if (evd_ptr != DAT_HANDLE_NULL) {
                cq_handle = evd_ptr->ib_cq_handle;
        } else if (ia_ptr->hca_ptr->null_ib_cq_handle != IB_INVALID_HANDLE) {
                cq_handle = ia_ptr->hca_ptr->null_ib_cq_handle;
        } else {
                cq_handle = (ib_cq_handle_t)
                    dapl_os_alloc(sizeof (struct dapls_ib_cq_handle));
                if (cq_handle == NULL) {
                        dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                            "dapli_get_dto_cq: cq malloc failed\n");
                        ia_ptr->hca_ptr->null_ib_cq_handle = IB_INVALID_HANDLE;
                        return (IB_INVALID_HANDLE);
                }

                /*
                 * create a fake a CQ, we don't bother to mmap this CQ
                 * since nobody know about it to reap events from it.
                 */
                (void) dapl_os_memzero(&create_msg, sizeof (create_msg));
                create_msg.evd_flags = DAT_EVD_DTO_FLAG;
                mcq = (mlnx_umap_cq_data_out_t *)create_msg.evd_cq_data_out;

                ia_fd = ia_ptr->hca_ptr->ib_hca_handle->ia_fd;

                /* call into driver to allocate cq */
                retval = ioctl(ia_fd, DAPL_EVD_CREATE, &create_msg);
                if (retval != 0) {
                        dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                            "dapli_get_dto_cq: DAPL_EVD_CREATE failed\n");
                        dapl_os_free(cq_handle,
                            sizeof (struct dapls_ib_cq_handle));
                        ia_ptr->hca_ptr->null_ib_cq_handle = IB_INVALID_HANDLE;
                        return (IB_INVALID_HANDLE);
                }

                (void) dapl_os_memzero(cq_handle,
                    sizeof (struct dapls_ib_cq_handle));
                dapl_os_lock_init(&cq_handle->cq_wrid_wqhdr_lock);
                cq_handle->evd_hkey = create_msg.evd_hkey;
                cq_handle->cq_addr = NULL;
                cq_handle->cq_map_offset = mcq->mcq_mapoffset;
                cq_handle->cq_map_len = mcq->mcq_maplen;
                cq_handle->cq_num = mcq->mcq_cqnum;
                cq_handle->cq_size = create_msg.evd_cq_real_size;
                cq_handle->cq_cqesz = mcq->mcq_cqesz;
                cq_handle->cq_iauar = ia_ptr->hca_ptr->ib_hca_handle->ia_uar;

                dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
                    "dapli_get_dto_cq: cq 0x%p created, hkey 0x%016llx\n",
                    cq_handle, create_msg.evd_hkey);

                /* save this dummy CQ handle into the hca */
                ia_ptr->hca_ptr->null_ib_cq_handle = cq_handle;
        }
        return (cq_handle);
}


/*
 * dapl_ib_qp_alloc
 *
 * Alloc a QP
 *
 * Input:
 *        *ep_ptr                pointer to EP INFO
 *        ib_hca_handle          provider HCA handle
 *        ib_pd_handle           provider protection domain handle
 *        cq_recv                provider recv CQ handle
 *        cq_send                provider send CQ handle
 *
 * Output:
 *        none
 *
 * Returns:
 *        DAT_SUCCESS
 *        DAT_INSUFFICIENT_RESOURCES
 *
 */
DAT_RETURN
dapls_ib_qp_alloc(
        IN DAPL_IA *ia_ptr,
        IN DAPL_EP *ep_ptr,
        IN DAPL_EP *ep_ctx_ptr)
{
        dapl_ep_create_t        ep_args;
        dapl_ep_free_t          epf_args;
        ib_qp_handle_t          qp_p;
        DAPL_SRQ                *srq_p;
        ib_cq_handle_t          cq_recv;
        ib_cq_handle_t          cq_send;
        DAPL_PZ                 *pz_handle;
        DAPL_EVD                *evd_handle;
        uint32_t                mpt_mask;
        size_t                  premev_size;
        uint32_t                i;
        int                     ia_fd;
        int                     hca_fd;
        DAT_RETURN              dat_status;
        int                     retval;
        mlnx_umap_qp_data_out_t *mqp;

        /* check parameters */
        if (ia_ptr->hca_ptr->ib_hca_handle == NULL) {
                dapl_dbg_log(DAPL_DBG_TYPE_EP,
                    "qp_alloc: hca_handle == NULL\n");
                return (DAT_INVALID_PARAMETER);
        }

        ia_fd = ia_ptr->hca_ptr->ib_hca_handle->ia_fd;
        hca_fd = ia_ptr->hca_ptr->ib_hca_handle->hca_fd;
        dapl_os_assert(ep_ptr->param.pz_handle != NULL);
        dapl_os_assert(ep_ptr->param.connect_evd_handle != NULL);

        /* fill in args for ep_create */
        (void) dapl_os_memzero(&ep_args, sizeof (ep_args));
        mqp = (mlnx_umap_qp_data_out_t *)ep_args.ep_qp_data_out;
        pz_handle = (DAPL_PZ *)ep_ptr->param.pz_handle;
        ep_args.ep_pd_hkey = pz_handle->pd_handle->pd_hkey;

        cq_recv = dapli_get_dto_cq(ia_ptr,
            (DAPL_EVD *)ep_ptr->param.recv_evd_handle);
        ep_args.ep_rcv_evd_hkey = cq_recv->evd_hkey;

        cq_send = dapli_get_dto_cq(ia_ptr,
            (DAPL_EVD *)ep_ptr->param.request_evd_handle);
        ep_args.ep_snd_evd_hkey = cq_send->evd_hkey;

        evd_handle = (DAPL_EVD *)ep_ptr->param.connect_evd_handle;
        ep_args.ep_conn_evd_hkey = evd_handle->ib_cq_handle->evd_hkey;

        ep_args.ep_ch_sizes.dcs_sq = ep_ptr->param.ep_attr.max_request_dtos;
        ep_args.ep_ch_sizes.dcs_sq_sgl = ep_ptr->param.ep_attr.max_request_iov;

        qp_p = (ib_qp_handle_t)dapl_os_alloc(
            sizeof (struct dapls_ib_qp_handle));
        if (qp_p == NULL) {
                dapl_dbg_log(DAPL_DBG_TYPE_EP,
                    "qp_alloc: os_alloc failed\n");
                return (DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
                    DAT_RESOURCE_MEMORY));
        }

        (void) dapl_os_memzero(qp_p, sizeof (*qp_p));

        if (ep_ptr->param.srq_handle == NULL) {
                premev_size = ep_ptr->param.ep_attr.max_recv_dtos *
                    sizeof (ib_work_completion_t);
                if (premev_size != 0) {
                        qp_p->qp_premature_events = (ib_work_completion_t *)
                            dapl_os_alloc(premev_size);
                        if (qp_p->qp_premature_events == NULL) {
                                dapl_dbg_log(DAPL_DBG_TYPE_EP,
                                    "qp_alloc:alloc premature_events failed\n");
                                dapl_os_free(qp_p, sizeof (*qp_p));
                                return (DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
                                    DAT_RESOURCE_MEMORY));
                        }
                }
                qp_p->qp_num_premature_events = 0;
                ep_args.ep_srq_hkey = 0;
                ep_args.ep_srq_attached = 0;
                ep_args.ep_ch_sizes.dcs_rq =
                    ep_ptr->param.ep_attr.max_recv_dtos;
                ep_args.ep_ch_sizes.dcs_rq_sgl =
                    ep_ptr->param.ep_attr.max_recv_iov;
        } else {
                premev_size = 0;
                srq_p = (DAPL_SRQ *)ep_ptr->param.srq_handle;
                /* premature events for EPs with SRQ sit on the SRQ */
                qp_p->qp_premature_events = srq_p->srq_handle->
                    srq_premature_events;
                qp_p->qp_num_premature_events = 0;
                ep_args.ep_srq_hkey = srq_p->srq_handle->srq_hkey;
                ep_args.ep_srq_attached = 1;
                ep_args.ep_ch_sizes.dcs_rq = 0;
                ep_args.ep_ch_sizes.dcs_rq_sgl = 0;
        }

        /*
         * there are cases when ep_ptr is a dummy container ep, and the orig
         * ep pointer is passed in ep_ctx_ptr. eg - dapl_ep_modify does this.
         * ep_cookie should be the actual ep pointer, not the dummy container
         * ep since the kernel returns this via events and the CM callback
         * routines
         */
        ep_args.ep_cookie = (uintptr_t)ep_ctx_ptr;

        dapl_dbg_log(DAPL_DBG_TYPE_EP,
            "qp_alloc: ep_ptr 0x%p, pz 0x%p (0x%llx), rcv_evd 0x%p (0x%llx)\n"
            "          snd_evd 0x%p (0x%llx), conn_evd 0x%p (0x%llx)\n"
            "          srq_hdl 0x%p (0x%llx)\n"
            "          sq_sz %d, rq_sz %d, sq_sgl_sz %d, rq_sgl_sz %d\n",
            ep_ptr, pz_handle, ep_args.ep_pd_hkey,
            ep_ptr->param.recv_evd_handle, ep_args.ep_rcv_evd_hkey,
            ep_ptr->param.request_evd_handle, ep_args.ep_snd_evd_hkey,
            ep_ptr->param.connect_evd_handle, ep_args.ep_conn_evd_hkey,
            ep_ptr->param.srq_handle, ep_args.ep_srq_hkey,
            ep_args.ep_ch_sizes.dcs_sq, ep_args.ep_ch_sizes.dcs_rq,
            ep_args.ep_ch_sizes.dcs_sq_sgl, ep_args.ep_ch_sizes.dcs_rq_sgl);

        /* The next line is only needed for backward compatibility */
        mqp->mqp_rev = MLNX_UMAP_IF_VERSION;
        retval = ioctl(ia_fd, DAPL_EP_CREATE, &ep_args);
        if (retval != 0 || mqp->mqp_rev != MLNX_UMAP_IF_VERSION) {
                dapl_dbg_log(DAPL_DBG_TYPE_EP,
                    "qp_alloc: ep_create failed errno %d, retval %d\n",
                    errno, retval);
                if (premev_size != 0) {
                        dapl_os_free(qp_p->qp_premature_events, premev_size);
                }
                dapl_os_free(qp_p, sizeof (*qp_p));
                return (dapls_convert_error(errno, retval));
        }

        /* In the case of Arbel or Hermon */
        if (mqp->mqp_sdbr_mapoffset != 0 || mqp->mqp_sdbr_maplen != 0)
                qp_p->qp_sq_dbp = dapls_ib_get_dbp(mqp->mqp_sdbr_maplen,
                    hca_fd, mqp->mqp_sdbr_mapoffset, mqp->mqp_sdbr_offset);
        if (mqp->mqp_rdbr_mapoffset != 0 || mqp->mqp_rdbr_maplen != 0)
                qp_p->qp_rq_dbp = dapls_ib_get_dbp(mqp->mqp_rdbr_maplen,
                    hca_fd, mqp->mqp_rdbr_mapoffset, mqp->mqp_rdbr_offset);

        qp_p->qp_addr = mmap64((void *)0, mqp->mqp_maplen,
            (PROT_READ | PROT_WRITE), MAP_SHARED, hca_fd,
            mqp->mqp_mapoffset);

        if (qp_p->qp_addr == MAP_FAILED ||
            qp_p->qp_sq_dbp == MAP_FAILED ||
            qp_p->qp_rq_dbp == MAP_FAILED) {
                dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                    "qp_alloc: mmap failed(%d)\n", errno);
                epf_args.epf_hkey = ep_args.ep_hkey;
                retval = ioctl(ia_fd, DAPL_EP_FREE, &epf_args);
                if (retval != 0) {
                        dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                            "qp_alloc: EP_FREE err:%d\n", errno);
                }
                if (premev_size != 0) {
                        dapl_os_free(qp_p->qp_premature_events, premev_size);
                }
                dapl_os_free(qp_p, sizeof (*qp_p));
                return (dapls_convert_error(errno, 0));
        }

        qp_p->qp_map_len = mqp->mqp_maplen;
        qp_p->qp_num = mqp->mqp_qpnum;
        qp_p->qp_iauar = ia_ptr->hca_ptr->ib_hca_handle->ia_uar;
        qp_p->qp_ia_bf = ia_ptr->hca_ptr->ib_hca_handle->ia_bf;
        qp_p->qp_ia_bf_toggle = ia_ptr->hca_ptr->ib_hca_handle->ia_bf_toggle;

        evd_handle = (DAPL_EVD *)ep_ptr->param.request_evd_handle;
        qp_p->qp_sq_cqhdl = evd_handle->ib_cq_handle;
        qp_p->qp_sq_lastwqeaddr = NULL;
        qp_p->qp_sq_wqhdr = NULL;
        qp_p->qp_sq_buf = (caddr_t)(qp_p->qp_addr + mqp->mqp_sq_off);
        qp_p->qp_sq_desc_addr = mqp->mqp_sq_desc_addr;
        qp_p->qp_sq_numwqe = mqp->mqp_sq_numwqe;
        qp_p->qp_sq_wqesz = mqp->mqp_sq_wqesz;
        qp_p->qp_sq_sgl = ep_ptr->param.ep_attr.max_request_iov;
        qp_p->qp_sq_inline = ia_ptr->hca_ptr->max_inline_send;
        qp_p->qp_sq_headroom = mqp->mqp_sq_headroomwqes;

        evd_handle = (DAPL_EVD *)ep_ptr->param.recv_evd_handle;
        qp_p->qp_rq_cqhdl = evd_handle->ib_cq_handle;
        qp_p->qp_rq_lastwqeaddr = NULL;
        qp_p->qp_rq_wqhdr = NULL;
        qp_p->qp_rq_buf = (caddr_t)(qp_p->qp_addr + mqp->mqp_rq_off);
        qp_p->qp_rq_desc_addr = mqp->mqp_rq_desc_addr;
        qp_p->qp_rq_numwqe = mqp->mqp_rq_numwqe;
        qp_p->qp_rq_wqesz = mqp->mqp_rq_wqesz;
        qp_p->qp_rq_sgl = ep_ptr->param.ep_attr.max_recv_iov;

        dapl_dbg_log(DAPL_DBG_TYPE_EP,
            "qp_alloc: created, qp_sq_buf %p, qp_rq_buf %p\n",
            qp_p->qp_sq_buf, qp_p->qp_rq_buf);
        dapl_dbg_log(DAPL_DBG_TYPE_EP,
            "qp_alloc: created, sq numwqe %x wqesz %x, rq numwqe %x wqesz %x\n",
            qp_p->qp_sq_numwqe, qp_p->qp_sq_wqesz,
            qp_p->qp_rq_numwqe, qp_p->qp_rq_wqesz);
        dapl_dbg_log(DAPL_DBG_TYPE_EP,
            "qp_alloc: created, qp_sq_desc_addr %x, qp_rq_desc_addr %x\n",
            mqp->mqp_sq_desc_addr, mqp->mqp_rq_desc_addr);
        dapl_dbg_log(DAPL_DBG_TYPE_EP,
            "qp_alloc: created, ep_ptr 0x%p, ep_hkey 0x%016llx\n\n",
            ep_ptr, ep_args.ep_hkey);

        qp_p->ep_hkey = ep_args.ep_hkey;

        /*
         * Calculate the number of bits in max_rmrs - this is indirectly
         * the max number of entried in the MPT table (defaults to 512K
         * but is configurable). This value is used while creating new
         * rkeys in bind processing (see dapl_tavor_hw.c).
         * Stash this value in the qp handle, don't want to do this math
         * for every bind
         */
        mpt_mask = (uint32_t)ia_ptr->hca_ptr->ia_attr.max_rmrs - 1;
        for (i = 0; mpt_mask > 0; mpt_mask = (mpt_mask >> 1), i++)
                ;
        qp_p->qp_num_mpt_shift = (uint32_t)i;

        ep_ptr->qpn = qp_p->qp_num;
        /* update the qp handle in the ep ptr */
        ep_ptr->qp_handle = qp_p;
        /*
         * ibt_alloc_rc_channel transitions the qp state to INIT.
         * hence we directly transition from UNATTACHED to INIT
         */
        ep_ptr->qp_state = IBT_STATE_INIT;

        if (ep_ptr->param.srq_handle) {
                /* insert ep into the SRQ's ep_table */
                dat_status = dapli_ib_srq_add_ep(srq_p->srq_handle,
                    qp_p->qp_num, ep_ptr);
                if (dat_status != DAT_SUCCESS) {
                        dapl_dbg_log(DAPL_DBG_TYPE_EP,
                            "qp_alloc: srq_add_ep failed ep_ptr 0x%p, 0x%x\n",
                            ep_ptr, dat_status);
                        (void) dapls_ib_qp_free(ia_ptr, ep_ptr);
                        return (DAT_INVALID_PARAMETER);
                }
                qp_p->qp_srq_enabled = 1;
                qp_p->qp_srq = srq_p->srq_handle;
        } else {
                qp_p->qp_srq_enabled = 0;
                qp_p->qp_srq = NULL;
        }
        DAPL_INIT_QP(ia_ptr)(qp_p);

        if (dapls_tavor_wrid_init(qp_p) != DAT_SUCCESS) {
                (void) dapls_ib_qp_free(ia_ptr, ep_ptr);
                return (DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
                    DAT_RESOURCE_MEMORY));
        }

        return (DAT_SUCCESS);
}


/*
 * dapls_ib_qp_free
 *
 * Free a QP
 *
 * Input:
 *        *ep_ptr                pointer to EP INFO
 *        ib_hca_handle          provider HCA handle
 *
 * Output:
 *        none
 *
 * Returns:
 *        none
 *
 */
DAT_RETURN
dapls_ib_qp_free(IN DAPL_IA *ia_ptr, IN DAPL_EP *ep_ptr)
{
        ib_qp_handle_t  qp_p = ep_ptr->qp_handle;
        ib_hca_handle_t ib_hca_handle = ia_ptr->hca_ptr->ib_hca_handle;
        dapl_ep_free_t  args;
        int             retval;

        if ((ep_ptr->qp_handle != IB_INVALID_HANDLE) &&
            (ep_ptr->qp_state != DAPL_QP_STATE_UNATTACHED)) {
                if (munmap((void *)qp_p->qp_addr, qp_p->qp_map_len) < 0) {
                        dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                            "qp_free: munmap failed(%d)\n", errno);
                }
                args.epf_hkey = qp_p->ep_hkey;
                retval = ioctl(ib_hca_handle->ia_fd, DAPL_EP_FREE, &args);
                if (retval != 0) {
                        dapl_dbg_log(DAPL_DBG_TYPE_EP,
                            "qp_free: ioctl errno = %d, retval = %d\n",
                            errno, retval);
                }
                dapl_dbg_log(DAPL_DBG_TYPE_EP,
                    "qp_free: freed, ep_ptr 0x%p, ep_hkey 0x%016llx\n",
                    ep_ptr, qp_p->ep_hkey);

                if (qp_p->qp_srq) {
                        dapli_ib_srq_remove_ep(qp_p->qp_srq, qp_p->qp_num);
                } else {
                        if (qp_p->qp_premature_events) {
                                dapl_os_free(qp_p->qp_premature_events,
                                    ep_ptr->param.ep_attr.max_recv_dtos *
                                    sizeof (ib_work_completion_t));
                        }
                }
                dapl_os_free(qp_p, sizeof (*qp_p));
                ep_ptr->qp_handle = NULL;
        }
        return (DAT_SUCCESS);
}


/*
 * dapl_ib_qp_modify
 *
 * Set the QP to the parameters specified in an EP_PARAM
 *
 * We can't be sure what state the QP is in so we first obtain the state
 * from the driver. The EP_PARAM structure that is provided has been
 * sanitized such that only non-zero values are valid.
 *
 * Input:
 *        ib_hca_handle          HCA handle
 *        qp_handle              QP handle
 *        ep_attr                Sanitized EP Params
 *
 * Output:
 *        none
 *
 * Returns:
 *        DAT_SUCCESS
 *        DAT_INSUFFICIENT_RESOURCES
 *        DAT_INVALID_PARAMETER
 *
 */
DAT_RETURN
dapls_ib_qp_modify(IN DAPL_IA *ia_ptr, IN DAPL_EP *ep_ptr,
    IN DAT_EP_ATTR *ep_attr)
{
        dapl_ep_modify_t        epm_args;
        boolean_t               epm_needed;
        int     ia_fd;
        int     retval;


        if (ep_ptr->qp_handle == NULL) {
                dapl_dbg_log(DAPL_DBG_TYPE_EP,
                    "qp_modify: qp_handle == NULL\n");
                return (DAT_INVALID_PARAMETER);
        }
        if (ia_ptr->hca_ptr->ib_hca_handle == NULL) {
                dapl_dbg_log(DAPL_DBG_TYPE_EP,
                    "qp_modify: hca_handle == NULL\n");
                return (DAT_INVALID_PARAMETER);
        }

        epm_needed = B_FALSE;

        /*
         * NOTE: ep_attr->max_mtu_size  indicates the maximum message
         * size, which is always 2GB for IB. Nothing to do with the IB
         * implementation, nothing to set up.
         */

        if (ep_attr->max_rdma_size > 0) {
                if (ep_attr->max_rdma_size > DAPL_IB_MAX_MESSAGE_SIZE) {
                        return (DAT_ERROR(DAT_INVALID_PARAMETER, 0));
                }
        }

        (void) memset((void *)&epm_args, 0, sizeof (epm_args));
        /*
         * The following parameters are dealt by creating a new qp
         * in dapl_ep_modify.
         *      - max_recv_dtos
         *      - max_request_dtos
         *      - max_recv_iov
         *      - max_request_iov
         */

        if (ep_attr->max_rdma_read_in > 0) {
                epm_args.epm_flags |= IBT_CEP_SET_RDMARA_IN;
                epm_args.epm_rdma_ra_in = ep_attr->max_rdma_read_in;
                epm_needed = B_TRUE;
        }
        if (ep_attr->max_rdma_read_out > 0) {
                epm_args.epm_flags |= IBT_CEP_SET_RDMARA_OUT;
                epm_args.epm_rdma_ra_out = ep_attr->max_rdma_read_out;
                epm_needed = B_TRUE;
        }

        if (!epm_needed) {
                dapl_dbg_log(DAPL_DBG_TYPE_EP,
                    "qp_modify: ep_hkey = %016llx nothing to do\n",
                    ep_ptr->qp_handle->ep_hkey);
                return (DAT_SUCCESS);
        }

        epm_args.epm_hkey = ep_ptr->qp_handle->ep_hkey;

        ia_fd = ia_ptr->hca_ptr->ib_hca_handle->ia_fd;

        retval = ioctl(ia_fd, DAPL_EP_MODIFY, &epm_args);
        if (retval != 0) {
                dapl_dbg_log(DAPL_DBG_TYPE_EP,
                    "qp_modify: ioctl failed errno %d, retval %d\n",
                    errno, retval);
                return (dapls_convert_error(errno, retval));
        }

        dapl_dbg_log(DAPL_DBG_TYPE_EP,
            "qp_modify: ep_hkey = %016llx\n", ep_ptr->qp_handle->ep_hkey);
        return (DAT_SUCCESS);
}

/*
 * Allocate the srq data structure as well as the kernel resource
 * corresponding to it.
 */
DAT_RETURN
dapls_ib_srq_alloc(IN DAPL_IA *ia_ptr, IN DAPL_SRQ *srq_ptr)
{
        dapl_srq_create_t       srqc_args;
        dapl_srq_free_t         srqf_args;
        ib_srq_handle_t         ibsrq_p;
        DAPL_PZ                 *pz_handle;
        uint32_t                i;
        size_t                  premev_size;
        size_t                  freeev_size;
        int                     ia_fd;
        int                     hca_fd;
        int                     retval;
        mlnx_umap_srq_data_out_t *msrq;

        /* check parameters */
        if (ia_ptr->hca_ptr->ib_hca_handle == NULL) {
                dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                    "srq_alloc: hca_handle == NULL\n");
                return (DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1));
        }

        ia_fd = ia_ptr->hca_ptr->ib_hca_handle->ia_fd;
        hca_fd = ia_ptr->hca_ptr->ib_hca_handle->hca_fd;
        dapl_os_assert(srq_ptr->param.pz_handle != NULL);

        /* fill in args for srq_create */
        pz_handle = (DAPL_PZ *)srq_ptr->param.pz_handle;

        ibsrq_p = (ib_srq_handle_t)dapl_os_alloc(sizeof (*ibsrq_p));
        if (ibsrq_p == NULL) {
                dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                    "srq_alloc: os_alloc failed\n");
                return (DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
                    DAT_RESOURCE_MEMORY));
        }
        (void) dapl_os_memzero(ibsrq_p, sizeof (*ibsrq_p));

        (void) dapl_os_memzero(&srqc_args, sizeof (srqc_args));
        msrq = (mlnx_umap_srq_data_out_t *)srqc_args.srqc_data_out;
        srqc_args.srqc_pd_hkey = pz_handle->pd_handle->pd_hkey;
        srqc_args.srqc_sizes.srqs_sz = srq_ptr->param.max_recv_dtos;
        srqc_args.srqc_sizes.srqs_sgl = srq_ptr->param.max_recv_iov;

        dapl_dbg_log(DAPL_DBG_TYPE_EP,
            "srq_alloc: srq_ptr 0x%p, pz 0x%p (0x%llx), srq_sz %d"
            " srq_sgl %d\n",
            srq_ptr, pz_handle, srqc_args.srqc_pd_hkey,
            srqc_args.srqc_sizes.srqs_sz, srqc_args.srqc_sizes.srqs_sgl);

        /* The next line is only needed for backward compatibility */
        msrq->msrq_rev = MLNX_UMAP_IF_VERSION;
        retval = ioctl(ia_fd, DAPL_SRQ_CREATE, &srqc_args);
        if (retval != 0 || msrq->msrq_rev != MLNX_UMAP_IF_VERSION) {
                dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                    "srq_alloc: srq_create failed errno %d, retval %d\n",
                    errno, retval);
                dapl_os_free(ibsrq_p, sizeof (*ibsrq_p));
                return (dapls_convert_error(errno, retval));
        }

        /* In the case of Arbel or Hermon */
        if (msrq->msrq_rdbr_mapoffset != 0 || msrq->msrq_rdbr_maplen != 0)
                ibsrq_p->srq_dbp = dapls_ib_get_dbp(
                    msrq->msrq_rdbr_maplen, hca_fd,
                    msrq->msrq_rdbr_mapoffset, msrq->msrq_rdbr_offset);

        ibsrq_p->srq_addr = mmap64((void *)0,
            msrq->msrq_maplen, (PROT_READ | PROT_WRITE),
            MAP_SHARED, hca_fd, msrq->msrq_mapoffset);

        if (ibsrq_p->srq_addr == MAP_FAILED ||
            ibsrq_p->srq_dbp == MAP_FAILED) {
                dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                    "srq_alloc: mmap failed(%d)\n", errno);
                srqf_args.srqf_hkey = srqc_args.srqc_hkey;
                retval = ioctl(ia_fd, DAPL_SRQ_FREE, &srqf_args);
                if (retval != 0) {
                        dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                            "srq_alloc: SRQ_FREE err:%d\n", errno);
                }
                dapl_os_free(ibsrq_p, sizeof (*ibsrq_p));
                return (dapls_convert_error(errno, 0));
        }

        ibsrq_p->srq_hkey = srqc_args.srqc_hkey;
        ibsrq_p->srq_map_len = msrq->msrq_maplen;
        ibsrq_p->srq_map_offset = msrq->msrq_mapoffset;
        ibsrq_p->srq_num = msrq->msrq_srqnum;
        ibsrq_p->srq_iauar = ia_ptr->hca_ptr->ib_hca_handle->ia_uar;
        /* since 0 is a valid index, -1 indicates invalid value */
        ibsrq_p->srq_wq_lastwqeindex = -1;
        ibsrq_p->srq_wq_desc_addr = msrq->msrq_desc_addr;
        ibsrq_p->srq_wq_numwqe = msrq->msrq_numwqe;
        ibsrq_p->srq_wq_wqesz = msrq->msrq_wqesz;
        ibsrq_p->srq_wq_sgl = srqc_args.srqc_real_sizes.srqs_sgl;

        /*
         * update the srq handle in the srq ptr, this is needed since from
         * here on cleanup is done by calling dapls_ib_srq_free()
         */
        srq_ptr->srq_handle = ibsrq_p;

        premev_size = ibsrq_p->srq_wq_numwqe * sizeof (ib_work_completion_t);
        ibsrq_p->srq_premature_events = (ib_work_completion_t *)
            dapl_os_alloc(premev_size);
        if (ibsrq_p->srq_premature_events == NULL) {
                dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                    "srq_alloc: os_alloc premature_events failed\n");
                dapls_ib_srq_free(ia_ptr, srq_ptr);
                srq_ptr->srq_handle = NULL;
                return (DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
                    DAT_RESOURCE_MEMORY));
        }

        freeev_size = ibsrq_p->srq_wq_numwqe * sizeof (uint32_t);
        ibsrq_p->srq_freepr_events = (uint32_t *)dapl_os_alloc(freeev_size);
        if (ibsrq_p->srq_freepr_events == NULL) {
                dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                    "srq_alloc: os_alloc freepr_events failed\n");
                dapls_ib_srq_free(ia_ptr, srq_ptr);
                srq_ptr->srq_handle = NULL;
                return (DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
                    DAT_RESOURCE_MEMORY));
        }
        ibsrq_p->srq_freepr_head = 0;
        ibsrq_p->srq_freepr_tail = 0;
        ibsrq_p->srq_freepr_num_events = ibsrq_p->srq_wq_numwqe;

        /* initialize the free list of premature events */
        for (i = 0; i < ibsrq_p->srq_freepr_num_events; i++) {
                ibsrq_p->srq_freepr_events[i] = i;
                /*
                 * wc_res_hash field is used to mark entries in the premature
                 * events list
                 */
                DAPL_SET_CQE_INVALID(&(ibsrq_p->srq_premature_events[i]));
        }

        dapl_dbg_log(DAPL_DBG_TYPE_EP,
            "srq_alloc: created, srq_ptr 0x%p, srq_hkey 0x%016llx\n",
            srq_ptr, srqc_args.srqc_hkey);

        DAPL_INIT_SRQ(ia_ptr)(ibsrq_p);

        if (dapls_tavor_srq_wrid_init(ibsrq_p) != DAT_SUCCESS) {
                dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                    "srq_alloc: wridlist alloc failed\n");
                dapls_ib_srq_free(ia_ptr, srq_ptr);
                srq_ptr->srq_handle = NULL;
                return (DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
                    DAT_RESOURCE_MEMORY));
        }
        ibsrq_p->srq_ep_table = NULL;
        /* allocate a hash table to to store EPs */
        retval = dapls_hash_create(DAPL_HASH_TABLE_DEFAULT_CAPACITY,
            DAT_FALSE, &ibsrq_p->srq_ep_table);
        if (retval != DAT_SUCCESS) {
                dapl_dbg_log(DAPL_DBG_TYPE_ERR, "dapls_ib_srq_alloc hash "
                    "create failed %d\n", retval);
                dapls_ib_srq_free(ia_ptr, srq_ptr);
                srq_ptr->srq_handle = NULL;
                return (retval);
        }

        return (DAT_SUCCESS);
}


/*
 * SRQ Free routine
 */
void
dapls_ib_srq_free(IN DAPL_IA *ia_handle, IN DAPL_SRQ *srq_ptr)
{
        ib_srq_handle_t srq_handle = srq_ptr->srq_handle;
        ib_hca_handle_t ib_hca_handle = ia_handle->hca_ptr->ib_hca_handle;
        dapl_srq_free_t srqf_args;
        int             retval;

        if (srq_handle == IB_INVALID_HANDLE) {
                return; /* nothing to do */
        }

        if (munmap((void *)srq_handle->srq_addr, srq_handle->srq_map_len) < 0) {
                dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                    "srq_free: munmap failed(%d)\n", errno);
        }
        srqf_args.srqf_hkey = srq_handle->srq_hkey;
        retval = ioctl(ib_hca_handle->ia_fd, DAPL_SRQ_FREE, &srqf_args);
        if (retval != 0) {
                dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                    "srq_free: ioctl errno = %d, retval = %d\n", errno, retval);
        }
        dapl_dbg_log(DAPL_DBG_TYPE_EP,
            "srq_free: freed, srq_ptr 0x%p, srq_hkey 0x%016llx\n",
            srq_ptr, srq_handle->srq_hkey);
        if (srq_handle->srq_ep_table) {
                (void) dapls_hash_free(srq_handle->srq_ep_table);
        }
        if (srq_handle->srq_wridlist) {
                dapls_tavor_srq_wrid_free(srq_handle);
        }
        if (srq_handle->srq_freepr_events) {
                dapl_os_free(srq_handle->srq_freepr_events,
                    srq_handle->srq_wq_numwqe * sizeof (ib_work_completion_t));
        }
        if (srq_handle->srq_premature_events) {
                dapl_os_free(srq_handle->srq_premature_events,
                    srq_handle->srq_wq_numwqe * sizeof (uint32_t));
        }
        dapl_os_free(srq_handle, sizeof (*srq_handle));
        srq_ptr->srq_handle = NULL;
}

/*
 * Adds EP to a hashtable in SRQ
 */
static DAT_RETURN
dapli_ib_srq_add_ep(IN ib_srq_handle_t srq_ptr, IN uint32_t qp_num,
    IN DAPL_EP *ep_ptr)
{
        DAPL_HASH_TABLE *htable;
        DAPL_HASH_KEY   key;

        dapl_os_assert(srq_ptr);

        htable = srq_ptr->srq_ep_table;
        key = qp_num;
        dapl_dbg_log(DAPL_DBG_TYPE_EP,
            "srq_insert_ep:%p %p %llx\n", srq_ptr, htable, key);
        return (dapls_hash_insert(htable, key, ep_ptr));
}

/*
 * Removes an EP from the hashtable in SRQ
 */
static void
dapli_ib_srq_remove_ep(IN ib_srq_handle_t srq_ptr, IN uint32_t qp_num)
{
        DAPL_HASH_TABLE *htable;
        DAPL_HASH_KEY   key;
        DAPL_EP         *epp;
        DAT_RETURN      retval;

        dapl_os_assert(srq_ptr);

        htable = srq_ptr->srq_ep_table;
        key = qp_num;

        retval = dapls_hash_remove(htable, key, (DAPL_HASH_DATA *)&epp);
        if (retval != DAT_SUCCESS) {
                dapl_dbg_log(DAPL_DBG_TYPE_EP,
                    "srq_remove_ep(%d): %p %llx\n", retval, htable, key);
        }
}

/*
 * Lookup an EP from the hashtable in SRQ
 */
DAPL_EP *
dapls_ib_srq_lookup_ep(IN DAPL_SRQ *srq_ptr, IN ib_work_completion_t *cqe_ptr)
{
        DAPL_HASH_TABLE *htable;
        DAPL_HASH_KEY   key;
        DAPL_EP         *epp;
        DAT_RETURN      retval;

        dapl_os_assert(srq_ptr && srq_ptr->srq_handle);

        htable = srq_ptr->srq_handle->srq_ep_table;
        key = DAPL_GET_CQE_QPN(cqe_ptr);
        epp = NULL;

        retval = dapls_hash_search(htable, key, (DAPL_HASH_DATA *)&epp);
        if (retval != DAT_SUCCESS) {
                dapl_dbg_log(DAPL_DBG_TYPE_EP,
                    "srq_lookup_ep(%x): %p %llx\n", retval, htable, key);
        }
        return (epp);
}


/*
 * dapl_ib_srq_resize
 *
 * Resize an SRQ
 *
 * Input:
 *      srq_ptr                 pointer to SRQ struct
 *      srqlen                  new length of the SRQ
 * Output:
 *      none
 *
 * Returns:
 *      DAT_SUCCESS
 *      DAT_INVALID_HANDLE
 *      DAT_INTERNAL_ERROR
 *      DAT_INSUFFICIENT_RESOURCES
 *
 */
DAT_RETURN
dapls_ib_srq_resize(
        IN  DAPL_SRQ            *srq_ptr,
        IN  DAT_COUNT           srqlen)
{
        ib_srq_handle_t srq_handle;
        DAT_RETURN      dat_status;

        dat_status = dapli_ib_srq_resize_internal(srq_ptr, srqlen);
        if (DAT_INSUFFICIENT_RESOURCES == DAT_GET_TYPE(dat_status)) {
                srq_handle = srq_ptr->srq_handle;
                /* attempt to resize back to the current size */
                dat_status = dapli_ib_srq_resize_internal(srq_ptr,
                    srq_handle->srq_wq_numwqe);
                if (DAT_SUCCESS != dat_status) {
                        /*
                         * XXX this is catastrophic need to post an event
                         * to the async evd
                         */
                        return (DAT_INTERNAL_ERROR);
                }
        }

        return (dat_status);
}

/*
 * dapli_ib_srq_resize_internal
 *
 * An internal routine to resize a SRQ.
 *
 * Input:
 *      srq_ptr                 pointer to SRQ struct
 *      srqlen                  new length of the srq
 * Output:
 *      none
 *
 * Returns:
 *      DAT_SUCCESS
 *      DAT_INVALID_HANDLE
 *      DAT_INSUFFICIENT_RESOURCES
 *
 */
static DAT_RETURN
dapli_ib_srq_resize_internal(
        IN  DAPL_SRQ            *srq_ptr,
        IN  DAT_COUNT           srqlen)
{
        ib_srq_handle_t         srq_handle;
        dapl_srq_resize_t       resize_msg;
        int                     ia_fd;
        int                     hca_fd;
        ib_work_completion_t    *new_premature_events;
        ib_work_completion_t    *old_premature_events;
        uint32_t                *new_freepr_events;
        uint32_t                *old_freepr_events;
        size_t                  old_premature_size;
        size_t                  old_freepr_size;
        size_t                  new_premature_size;
        size_t                  new_freepr_size;
        int                     idx, i;
        int                     retval;
        mlnx_umap_srq_data_out_t *msrq;

        dapl_dbg_log(DAPL_DBG_TYPE_EP,
            "dapls_ib_srq_resize: srq 0x%p srq_hdl 0x%p "
            "srq_hkey 0x%016llx srqlen %d\n",
            srq_ptr, (void *)srq_ptr->srq_handle,
            srq_ptr->srq_handle->srq_hkey, srqlen);

        srq_handle = srq_ptr->srq_handle;
        /*
         * Since SRQs are created in powers of 2 its possible that the
         * previously allocated SRQ has sufficient entries. If the current
         * SRQ is big enough and it is mapped we are done.
         */
        if ((srqlen < srq_handle->srq_wq_numwqe) && (srq_handle->srq_addr)) {
                return (DAT_SUCCESS);
        }

        /* unmap the SRQ before resizing it */
        if ((srq_handle->srq_addr) && (munmap((char *)srq_handle->srq_addr,
            srq_handle->srq_map_len) < 0)) {
                dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                    "srq_resize: munmap(%p:0x%llx) failed(%d)\n",
                    srq_handle->srq_addr, srq_handle->srq_map_len, errno);
                return (DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_SRQ));
        }
        /* srq_addr is unmapped and no longer valid */
        srq_handle->srq_addr = NULL;

        ia_fd = srq_ptr->header.owner_ia->hca_ptr->ib_hca_handle->ia_fd;
        hca_fd = srq_ptr->header.owner_ia->hca_ptr->ib_hca_handle->hca_fd;

        (void) dapl_os_memzero(&resize_msg, sizeof (resize_msg));
        resize_msg.srqr_hkey = srq_handle->srq_hkey;
        resize_msg.srqr_new_size = srqlen;
        msrq = (mlnx_umap_srq_data_out_t *)resize_msg.srqr_data_out;

        /* The next line is only needed for backward compatibility */
        msrq->msrq_rev = MLNX_UMAP_IF_VERSION;
        retval = ioctl(ia_fd, DAPL_SRQ_RESIZE, &resize_msg);
        if (retval != 0 || msrq->msrq_rev != MLNX_UMAP_IF_VERSION) {
                dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                    "dapls_ib_srq_resize: srq 0x%p, err: %s\n",
                    srq_ptr, strerror(errno));
                if (errno == EINVAL) { /* Couldn't find this srq */
                        return (DAT_ERROR(DAT_INVALID_HANDLE,
                            DAT_INVALID_HANDLE_SRQ));
                } else { /* Need to retry resize with a smaller qlen */
                        return (DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
                            DAT_RESOURCE_SRQ));
                }
        }

        dapl_os_assert(srq_handle->srq_num == msrq->msrq_srqnum);

        /* In the case of Arbel or Hermon */
        if (msrq->msrq_rdbr_mapoffset != 0 ||
            msrq->msrq_rdbr_maplen != 0)
                srq_handle->srq_dbp = dapls_ib_get_dbp(
                    msrq->msrq_rdbr_maplen,
                    hca_fd, msrq->msrq_rdbr_mapoffset,
                    msrq->msrq_rdbr_offset);

        srq_handle->srq_addr = mmap64((void *)0,
            msrq->msrq_maplen, (PROT_READ | PROT_WRITE),
            MAP_SHARED, hca_fd, msrq->msrq_mapoffset);

        if (srq_handle->srq_addr == MAP_FAILED ||
            srq_handle->srq_dbp == MAP_FAILED) {
                srq_handle->srq_addr = NULL;
                dapl_dbg_log(DAPL_DBG_TYPE_ERR,
                    "srq_resize: mmap failed(%d)\n", errno);
                /* Need to retry resize with a smaller qlen */
                return (DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
                    DAT_RESOURCE_MEMORY));
        }

        old_freepr_size = srq_handle->srq_wq_numwqe * sizeof (uint32_t);
        old_premature_size = srq_handle->srq_wq_numwqe *
            sizeof (ib_work_completion_t);

        old_freepr_events = srq_handle->srq_freepr_events;
        old_premature_events = srq_handle->srq_premature_events;

        new_freepr_size = resize_msg.srqr_real_size * sizeof (uint32_t);
        new_premature_size = resize_msg.srqr_real_size *
            sizeof (ib_work_completion_t);

        new_freepr_events = (uint32_t *)dapl_os_alloc(new_freepr_size);
        if (new_freepr_events == NULL) {
                goto bail;
        }
        new_premature_events = (ib_work_completion_t *)dapl_os_alloc(
            new_premature_size);
        if (new_premature_events == NULL) {
                goto bail;
        }
        if (!dapls_tavor_srq_wrid_resize(srq_handle,
            resize_msg.srqr_real_size)) {
                goto bail;
        }
        idx = 0;
        /* copy valid premature events  */
        for (i = 0; i < srq_handle->srq_wq_numwqe; i++) {
                if (!DAPL_CQE_IS_VALID(&old_premature_events[i])) {
                        continue;
                }
                (void) dapl_os_memcpy(&new_premature_events[idx],
                    &old_premature_events[i], sizeof (ib_work_completion_t));
                idx++;
        }
        dapl_os_assert(srq_handle->srq_wq_numwqe - idx ==
            srq_handle->srq_freepr_num_events);

        /* Initialize free events lists */
        for (i = 0; i < resize_msg.srqr_real_size - idx; i++) {
                new_freepr_events[i] = idx + i;
        }

        srq_handle->srq_freepr_events = new_freepr_events;
        srq_handle->srq_premature_events = new_premature_events;
        srq_handle->srq_freepr_num_events = resize_msg.srqr_real_size - idx;
        srq_handle->srq_freepr_head = 0;
        /* a full freepr list has tail at 0 */
        if (idx == 0) {
                srq_handle->srq_freepr_tail = 0;
        } else {
                srq_handle->srq_freepr_tail = srq_handle->srq_freepr_num_events;
        }

        if (old_freepr_events) {
                old_freepr_size = old_freepr_size; /* pacify lint */
                dapl_os_free(old_freepr_events, old_freepr_size);
        }
        if (old_premature_events) {
                old_premature_size = old_premature_size; /* pacify lint */
                dapl_os_free(old_premature_events, old_premature_size);
        }

        /*
         * update the srq fields,
         * note: the srq_wq_lastwqeindex doesn't change since the old
         * work queue is copied as a whole into the new work queue.
         */
        srq_handle->srq_map_offset = msrq->msrq_mapoffset;
        srq_handle->srq_map_len = msrq->msrq_maplen;
        srq_handle->srq_wq_desc_addr = msrq->msrq_desc_addr;
        srq_handle->srq_wq_numwqe = msrq->msrq_numwqe;
        srq_handle->srq_wq_wqesz = msrq->msrq_wqesz;

        return (DAT_SUCCESS);
bail:
        if (new_freepr_events) {
                dapl_os_free(new_freepr_events, new_freepr_size);
        }
        if (new_premature_events) {
                dapl_os_free(new_premature_events, new_premature_size);
        }
        return (DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY));
}