30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * CDDL HEADER START
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap *
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * The contents of this file are subject to the terms of the
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Common Development and Distribution License (the "License").
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * You may not use this file except in compliance with the License.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap *
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * or http://www.opensolaris.org/os/licensing.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * See the License for the specific language governing permissions
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * and limitations under the License.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap *
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * When distributing Covered Code, include this CDDL HEADER in each
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * If applicable, add the following below this CDDL HEADER, with the
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * fields enclosed by brackets "[]" replaced with your own identifying
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * information: Portions Copyright [yyyy] [name of copyright owner]
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap *
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * CDDL HEADER END
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Use is subject to license terms.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#include <sys/types.h>
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#include <sys/ddi.h>
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#include <sys/types.h>
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#include <sys/socket.h>
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#include <netinet/in.h>
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#include <sys/sunddi.h>
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#include <sys/sysmacros.h>
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#include <sys/ib/ibtl/ibti.h>
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#include <sys/ib/ibtl/ibtl_types.h>
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap#include <sys/ib/clients/iser/iser.h>
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * iser_resource.c
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Routines for allocating resources for iSER
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic iser_mr_t *iser_vmem_chunk_alloc(iser_hca_t *hca, ib_memlen_t chunksize,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ibt_mr_flags_t mr_flags);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void iser_vmem_chunk_free(iser_hca_t *hca, iser_mr_t *iser_mr);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic iser_mr_t *iser_reg_mem(iser_hca_t *hca, ib_vaddr_t vaddr,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ib_memlen_t len, ibt_mr_flags_t mr_flags);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void iser_dereg_mem(iser_hca_t *hca, iser_mr_t *mr);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic int iser_vmem_mr_compare(const void *void_mr1, const void *void_mr2);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * iser_init_hca_caches()
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Invoked per HCA instance initialization, to establish HCA-wide
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * message and buffer kmem caches. Note we'll uniquify cache names
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * with the lower 32-bits of the HCA GUID.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapvoid
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_init_hca_caches(iser_hca_t *hca)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap char name[ISER_CACHE_NAMELEN];
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (void) snprintf(name, ISER_CACHE_NAMELEN, "iser_msg_pool_%08x",
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (uint32_t)(hca->hca_guid & 0xFFFFFFFF));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hca->hca_msg_pool = iser_vmem_create(name, hca, ISER_MSG_MR_CHUNKSIZE,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_MSG_POOL_MAX, ISER_MSG_MR_FLAGS);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (void) snprintf(name, ISER_CACHE_NAMELEN, "iser_msg_cache_%08x",
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (uint32_t)(hca->hca_guid & 0xFFFFFFFF));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hca->iser_msg_cache = kmem_cache_create(name, sizeof (iser_msg_t),
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap 0, &iser_msg_cache_constructor, &iser_msg_cache_destructor,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap NULL, hca, NULL, KM_SLEEP);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (void) snprintf(name, ISER_CACHE_NAMELEN, "iser_buf_pool_%08x",
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (uint32_t)(hca->hca_guid & 0xFFFFFFFF));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hca->hca_buf_pool = iser_vmem_create(name, hca, ISER_BUF_MR_CHUNKSIZE,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_BUF_POOL_MAX, ISER_BUF_MR_FLAGS);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (void) snprintf(name, ISER_CACHE_NAMELEN, "iser_buf_cache_%08x",
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (uint32_t)(hca->hca_guid & 0xFFFFFFFF));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap hca->iser_buf_cache = kmem_cache_create(name, sizeof (iser_buf_t),
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap 0, &iser_buf_cache_constructor, &iser_buf_cache_destructor,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap NULL, hca, NULL, KM_SLEEP);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * iser_fini_hca_caches()
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Invoked per HCA instance teardown, this routine cleans up the
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * message and buffer handle caches.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapvoid
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_fini_hca_caches(iser_hca_t *hca)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap kmem_cache_destroy(hca->iser_buf_cache);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_vmem_destroy(hca->hca_buf_pool);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap kmem_cache_destroy(hca->iser_msg_cache);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_vmem_destroy(hca->hca_msg_pool);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Allocate and initialize an iSER WR handle
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_wr_t *
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_wr_get()
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr_t *iser_wr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr = kmem_cache_alloc(iser_state->iser_wr_cache, KM_NOSLEEP);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (iser_wr != NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr->iw_type = ISER_WR_UNDEFINED;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr->iw_msg = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr->iw_buf = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_wr->iw_pdu = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (iser_wr);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Free an iSER WR handle back to the global cache
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapvoid
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_wr_free(iser_wr_t *iser_wr)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap kmem_cache_free(iser_state->iser_wr_cache, iser_wr);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * iser_msg_cache_constructor()
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Allocate and register memory for an iSER Control-type PDU message.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * The cached objects will retain this memory registration in the HCA,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * and thus provide a cache of pre-allocated and registered messages
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * for use in iSER.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/* ARGSUSED */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapint
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_msg_cache_constructor(void *msg_void, void *arg, int flags)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap void *memp = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap int status;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_msg_t *msg = (iser_msg_t *)msg_void;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_hca_t *hca = (iser_hca_t *)arg;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_mr_t mr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap memp = iser_vmem_alloc(hca->hca_msg_pool, ISER_MAX_CTRLPDU_LEN);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (memp == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_msg_cache_constructor: "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "failed to allocate backing memory");
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (DDI_FAILURE);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Fill in iser_mr for the memory we just allocated */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = iser_vmem_mr(hca->hca_msg_pool, memp,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_MAX_CTRLPDU_LEN, &mr);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (status != IDM_STATUS_SUCCESS) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_msg_cache_constructor: "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "couldn't find mr for %p", memp);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_vmem_free(hca->hca_msg_pool, memp, ISER_MAX_CTRLPDU_LEN);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (DDI_FAILURE);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap msg->msg_ds.ds_va = (ib_vaddr_t)(uintptr_t)memp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap msg->msg_ds.ds_key = mr.is_mrlkey;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Set a backpointer to this cache to save a lookup on free */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap msg->cache = hca->iser_msg_cache;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (DDI_SUCCESS);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Deregister and free registered memory from an iser_msg_t handle.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapvoid
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_msg_cache_destructor(void *mr, void *arg)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_msg_t *msg = (iser_msg_t *)mr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_hca_t *hca = (iser_hca_t *)arg;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap uint8_t *memp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap memp = (uint8_t *)(uintptr_t)(ib_vaddr_t)msg->msg_ds.ds_va;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_vmem_free(hca->hca_msg_pool, memp, ISER_MAX_CTRLPDU_LEN);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Pull a msg handle off of hca's msg cache. If no object is available
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * on the cache, a new message buffer will be allocated and registered
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * with the HCA. Once freed, this message will not be unregistered, thus
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * building up a cache of pre-allocated and registered message buffers
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * over time.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_msg_t *
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_msg_get(iser_hca_t *hca, int num, int *ret)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_msg_t *tmp, *msg = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap int i;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(hca != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Pull num number of message handles off the cache, linking
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * them if more than one have been requested.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap for (i = 0; i < num; i++) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap tmp = kmem_cache_alloc(hca->iser_msg_cache, KM_NOSLEEP);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (tmp == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_msg_get: alloc failed, "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "requested (%d) allocated (%d)", num, i);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap break;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap tmp->msg_ds.ds_len = ISER_MAX_CTRLPDU_LEN;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap tmp->nextp = msg;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap msg = tmp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (ret != NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap *ret = i;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (msg);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Free this msg back to its cache, leaving the memory contained by
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * it registered for later re-use.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapvoid
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_msg_free(iser_msg_t *msg)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap kmem_cache_free(msg->cache, msg);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * iser_buf_cache_constructor()
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Allocate and register memory for an iSER RDMA operation. The cached
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * objects will retain this memory registration in the HCA, and thus
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * provide a cache of pre-allocated and registered messages for use in
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * iSER.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/* ARGSUSED */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapint
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_buf_cache_constructor(void *mr, void *arg, int flags)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap uint8_t *memp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_status_t status;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_buf_t *iser_buf = (iser_buf_t *)mr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_hca_t *hca = (iser_hca_t *)arg;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Allocate an iser_mr handle for this buffer */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_buf->iser_mr = kmem_zalloc(sizeof (iser_mr_t), KM_NOSLEEP);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (iser_buf->iser_mr == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_buf_cache_constructor: "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "failed to allocate memory for iser_mr handle");
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (DDI_FAILURE);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap memp = iser_vmem_alloc(hca->hca_buf_pool, ISER_DEFAULT_BUFLEN);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (memp == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap kmem_free(iser_buf->iser_mr, sizeof (iser_mr_t));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (DDI_FAILURE);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Fill in iser_mr for the memory we just allocated */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = iser_vmem_mr(hca->hca_buf_pool, memp, ISER_DEFAULT_BUFLEN,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_buf->iser_mr);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (status != IDM_STATUS_SUCCESS) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (DDI_FAILURE);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Set buf pointer and len for later manipulation (if necessary) */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_buf->buf = (uint64_t *)(uintptr_t)memp;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_buf->buflen = ISER_DEFAULT_BUFLEN;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Populate the SGE Vaddr and L_key for the xfer operation later */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_buf->buf_ds.ds_va = iser_buf->iser_mr->is_mrva;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_buf->buf_ds.ds_key = iser_buf->iser_mr->is_mrlkey;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Set a backpointer to this cache to save a lookup on free */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_buf->cache = hca->iser_buf_cache;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap gethrestime(&iser_buf->buf_constructed);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (DDI_SUCCESS);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Deregister and free registered memory from an iser_buf_t handle.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapvoid
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_buf_cache_destructor(void *mr, void *arg)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_buf_t *iser_buf = (iser_buf_t *)mr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_hca_t *hca = (iser_hca_t *)arg;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap gethrestime(&iser_buf->buf_destructed);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_vmem_free(hca->hca_buf_pool, iser_buf->buf, iser_buf->buflen);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap kmem_free(iser_buf->iser_mr, sizeof (iser_mr_t));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap/*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Registration for initiator buffers
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapint
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_reg_rdma_mem(iser_hca_t *hca, idm_buf_t *idb)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_mr_t *iser_mr = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(idb != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(idb->idb_buflen > 0);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_mr = iser_reg_mem(hca, (ib_vaddr_t)(uintptr_t)idb->idb_buf,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idb->idb_buflen, ISER_BUF_MR_FLAGS | IBT_MR_NOSLEEP);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (iser_mr == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_reg_rdma_mem: failed to register "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "memory for idm_buf_t");
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (DDI_FAILURE);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idb->idb_reg_private = (void *)iser_mr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (DDI_SUCCESS);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapvoid
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_dereg_rdma_mem(iser_hca_t *hca, idm_buf_t *idb)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_mr_t *mr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(idb != NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mr = (iser_mr_t *)idb->idb_reg_private;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_dereg_mem(hca, mr);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_vmem_mr_pool_t *
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_vmem_create(const char *name, iser_hca_t *hca, ib_memlen_t chunksize,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap uint64_t max_total_size, ibt_mr_flags_t arena_mr_flags)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_mr_t *first_chunk;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_vmem_mr_pool_t *result;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(chunksize <= max_total_size);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap result = kmem_zalloc(sizeof (*result), KM_SLEEP);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap result->ivmp_hca = hca;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap result->ivmp_mr_flags = arena_mr_flags;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap result->ivmp_chunksize = chunksize;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap result->ivmp_max_total_size = max_total_size;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_init(&result->ivmp_mutex, NULL, MUTEX_DRIVER, NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap avl_create(&result->ivmp_mr_list, iser_vmem_mr_compare,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap sizeof (iser_mr_t), offsetof(iser_mr_t, is_avl_ln));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap first_chunk = iser_vmem_chunk_alloc(hca, chunksize,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap arena_mr_flags | IBT_MR_SLEEP);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap avl_add(&result->ivmp_mr_list, first_chunk);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap result->ivmp_total_size += chunksize;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap result->ivmp_vmem = vmem_create(name,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (void *)(uintptr_t)first_chunk->is_mrva,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (size_t)first_chunk->is_mrlen, ISER_MR_QUANTSIZE,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap NULL, NULL, NULL, 0, VM_SLEEP);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (result);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapvoid
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_vmem_destroy(iser_vmem_mr_pool_t *vmr_pool)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_mr_t *chunk, *next_chunk;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_enter(&vmr_pool->ivmp_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap vmem_destroy(vmr_pool->ivmp_vmem);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap for (chunk = avl_first(&vmr_pool->ivmp_mr_list); chunk != NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap chunk = next_chunk) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap next_chunk = AVL_NEXT(&vmr_pool->ivmp_mr_list, chunk);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap avl_remove(&vmr_pool->ivmp_mr_list, chunk);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_vmem_chunk_free(vmr_pool->ivmp_hca, chunk);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&vmr_pool->ivmp_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap avl_destroy(&vmr_pool->ivmp_mr_list);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_destroy(&vmr_pool->ivmp_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap kmem_free(vmr_pool, sizeof (*vmr_pool));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapvoid *
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_vmem_alloc(iser_vmem_mr_pool_t *vmr_pool, size_t size)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap void *result;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_mr_t *next_chunk;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ib_memlen_t chunk_len;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap result = vmem_alloc(vmr_pool->ivmp_vmem, size,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap VM_NOSLEEP | VM_FIRSTFIT);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (result == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_enter(&vmr_pool->ivmp_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap chunk_len = vmr_pool->ivmp_chunksize;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if ((vmr_pool->ivmp_total_size + chunk_len) >
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap vmr_pool->ivmp_max_total_size) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Don't go over the pool size limit. We can allocate
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * partial chunks so it's not always the case that
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * current_size + chunk_size == max_total_size
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (vmr_pool->ivmp_total_size >=
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap vmr_pool->ivmp_max_total_size) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&vmr_pool->ivmp_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap chunk_len = vmr_pool->ivmp_max_total_size -
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap vmr_pool->ivmp_total_size;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap next_chunk = iser_vmem_chunk_alloc(vmr_pool->ivmp_hca,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap chunk_len, vmr_pool->ivmp_mr_flags | IBT_MR_NOSLEEP);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (next_chunk != NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (vmem_add(vmr_pool->ivmp_vmem,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (void *)(uintptr_t)next_chunk->is_mrva,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap next_chunk->is_mrlen, VM_NOSLEEP) == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Free the chunk we just allocated */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_vmem_chunk_free(vmr_pool->ivmp_hca,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap next_chunk);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap vmr_pool->ivmp_total_size +=
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap next_chunk->is_mrlen;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap avl_add(&vmr_pool->ivmp_mr_list, next_chunk);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap result = vmem_alloc(vmr_pool->ivmp_vmem, size,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap VM_NOSLEEP | VM_FIRSTFIT);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&vmr_pool->ivmp_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (result);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapvoid
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_vmem_free(iser_vmem_mr_pool_t *vmr_pool, void *vaddr, size_t size)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap vmem_free(vmr_pool->ivmp_vmem, vaddr, size);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapidm_status_t
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_vmem_mr(iser_vmem_mr_pool_t *vmr_pool, void *vaddr, size_t size,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_mr_t *mr)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap avl_index_t where;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ib_vaddr_t mrva = (ib_vaddr_t)(uintptr_t)vaddr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_mr_t search_chunk;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_mr_t *nearest_chunk;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ib_vaddr_t chunk_end;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_enter(&vmr_pool->ivmp_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap search_chunk.is_mrva = mrva;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap nearest_chunk = avl_find(&vmr_pool->ivmp_mr_list, &search_chunk,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap &where);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (nearest_chunk == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap nearest_chunk = avl_nearest(&vmr_pool->ivmp_mr_list, where,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap AVL_BEFORE);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (nearest_chunk == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&vmr_pool->ivmp_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_FAIL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* See if this chunk contains the specified address range */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(nearest_chunk->is_mrva <= mrva);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap chunk_end = nearest_chunk->is_mrva + nearest_chunk->is_mrlen;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (chunk_end >= mrva + size) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Yes, this chunk contains the address range */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mr->is_mrhdl = nearest_chunk->is_mrhdl;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mr->is_mrva = mrva;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mr->is_mrlen = size;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mr->is_mrlkey = nearest_chunk->is_mrlkey;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mr->is_mrrkey = nearest_chunk->is_mrrkey;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&vmr_pool->ivmp_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_SUCCESS);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&vmr_pool->ivmp_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_FAIL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic iser_mr_t *
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_vmem_chunk_alloc(iser_hca_t *hca, ib_memlen_t chunksize,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ibt_mr_flags_t mr_flags)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap void *chunk = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_mr_t *result = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap int km_flags = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (mr_flags & IBT_MR_NOSLEEP)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap km_flags |= KM_NOSLEEP;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap while ((chunk == NULL) && (chunksize >= ISER_MIN_CHUNKSIZE)) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap chunk = kmem_alloc(chunksize, km_flags);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (chunk == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_vmem_chunk_alloc: "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "chunk alloc of %d failed, trying %d",
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (int)chunksize, (int)(chunksize / 2));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap chunksize /= 2;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_vmem_chunk_alloc: "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "New chunk %p size %d", chunk, (int)chunksize);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (chunk != NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap result = iser_reg_mem(hca, (ib_vaddr_t)(uintptr_t)chunk,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap chunksize, mr_flags);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (result == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_vmem_chunk_alloc: "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "Chunk registration failed");
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap kmem_free(chunk, chunksize);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (result);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_vmem_chunk_free(iser_hca_t *hca, iser_mr_t *iser_mr)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap void *chunk = (void *)(uintptr_t)iser_mr->is_mrva;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ib_memlen_t chunksize = iser_mr->is_mrlen;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_dereg_mem(hca, iser_mr);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap kmem_free(chunk, chunksize);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_mr_t *
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_reg_mem(iser_hca_t *hca, ib_vaddr_t vaddr, ib_memlen_t len,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ibt_mr_flags_t mr_flags)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_mr_t *result = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ibt_mr_attr_t mr_attr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ibt_mr_desc_t mr_desc;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ibt_status_t status;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap int km_flags = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (mr_flags & IBT_MR_NOSLEEP)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mr_flags |= KM_NOSLEEP;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap result = (iser_mr_t *)kmem_zalloc(sizeof (iser_mr_t), km_flags);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (result == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_reg_mem: failed to allocate "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "memory for iser_mr handle");
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bzero(&mr_attr, sizeof (ibt_mr_attr_t));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bzero(&mr_desc, sizeof (ibt_mr_desc_t));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mr_attr.mr_vaddr = vaddr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mr_attr.mr_len = len;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mr_attr.mr_as = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mr_attr.mr_flags = mr_flags;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap status = ibt_register_mr(hca->hca_hdl, hca->hca_pdhdl, &mr_attr,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap &result->is_mrhdl, &mr_desc);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (status != IBT_SUCCESS) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISER_LOG(CE_NOTE, "iser_reg_mem: ibt_register_mr "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "failure (%d)", status);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap kmem_free(result, sizeof (iser_mr_t));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (NULL);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap result->is_mrva = mr_attr.mr_vaddr;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap result->is_mrlen = mr_attr.mr_len;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap result->is_mrlkey = mr_desc.md_lkey;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap result->is_mrrkey = mr_desc.md_rkey;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (result);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapvoid
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_dereg_mem(iser_hca_t *hca, iser_mr_t *mr)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
aedf2b3bb56b025fcaf87b49ec6c8aeea07f16d7srivijitha dugganapalli (void) ibt_deregister_mr(hca->hca_hdl, mr->is_mrhdl);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap kmem_free(mr, sizeof (iser_mr_t));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic int
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiser_vmem_mr_compare(const void *void_mr1, const void *void_mr2)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_mr_t *mr1 = (iser_mr_t *)void_mr1;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap iser_mr_t *mr2 = (iser_mr_t *)void_mr2;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Sort memory chunks by their virtual address */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (mr1->is_mrva < mr2->is_mrva)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (-1);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap else if (mr1->is_mrva > mr2->is_mrva)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (1);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (0);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}