xref: /onnv-gate/usr/src/uts/common/io/ib/clients/iser/iser_resource.c (revision 11093:92e0bcf89283)
19162SPeter.Dunlap@Sun.COM /*
29162SPeter.Dunlap@Sun.COM  * CDDL HEADER START
39162SPeter.Dunlap@Sun.COM  *
49162SPeter.Dunlap@Sun.COM  * The contents of this file are subject to the terms of the
59162SPeter.Dunlap@Sun.COM  * Common Development and Distribution License (the "License").
69162SPeter.Dunlap@Sun.COM  * You may not use this file except in compliance with the License.
79162SPeter.Dunlap@Sun.COM  *
89162SPeter.Dunlap@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99162SPeter.Dunlap@Sun.COM  * or http://www.opensolaris.org/os/licensing.
109162SPeter.Dunlap@Sun.COM  * See the License for the specific language governing permissions
119162SPeter.Dunlap@Sun.COM  * and limitations under the License.
129162SPeter.Dunlap@Sun.COM  *
139162SPeter.Dunlap@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
149162SPeter.Dunlap@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159162SPeter.Dunlap@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
169162SPeter.Dunlap@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
179162SPeter.Dunlap@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
189162SPeter.Dunlap@Sun.COM  *
199162SPeter.Dunlap@Sun.COM  * CDDL HEADER END
209162SPeter.Dunlap@Sun.COM  */
219162SPeter.Dunlap@Sun.COM /*
229162SPeter.Dunlap@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
239162SPeter.Dunlap@Sun.COM  * Use is subject to license terms.
249162SPeter.Dunlap@Sun.COM  */
259162SPeter.Dunlap@Sun.COM 
269162SPeter.Dunlap@Sun.COM #include <sys/types.h>
279162SPeter.Dunlap@Sun.COM #include <sys/ddi.h>
289162SPeter.Dunlap@Sun.COM #include <sys/types.h>
299162SPeter.Dunlap@Sun.COM #include <sys/socket.h>
309162SPeter.Dunlap@Sun.COM #include <netinet/in.h>
319162SPeter.Dunlap@Sun.COM #include <sys/sunddi.h>
329162SPeter.Dunlap@Sun.COM #include <sys/sysmacros.h>
339162SPeter.Dunlap@Sun.COM #include <sys/ib/ibtl/ibti.h>
349162SPeter.Dunlap@Sun.COM #include <sys/ib/ibtl/ibtl_types.h>
359162SPeter.Dunlap@Sun.COM 
369162SPeter.Dunlap@Sun.COM #include <sys/ib/clients/iser/iser.h>
379162SPeter.Dunlap@Sun.COM 
389162SPeter.Dunlap@Sun.COM /*
399162SPeter.Dunlap@Sun.COM  * iser_resource.c
409162SPeter.Dunlap@Sun.COM  *    Routines for allocating resources for iSER
419162SPeter.Dunlap@Sun.COM  */
429162SPeter.Dunlap@Sun.COM 
439162SPeter.Dunlap@Sun.COM static iser_mr_t *iser_vmem_chunk_alloc(iser_hca_t *hca, ib_memlen_t chunksize,
449162SPeter.Dunlap@Sun.COM     ibt_mr_flags_t mr_flags);
459162SPeter.Dunlap@Sun.COM 
469162SPeter.Dunlap@Sun.COM static void iser_vmem_chunk_free(iser_hca_t *hca, iser_mr_t *iser_mr);
479162SPeter.Dunlap@Sun.COM 
489162SPeter.Dunlap@Sun.COM static iser_mr_t *iser_reg_mem(iser_hca_t *hca, ib_vaddr_t vaddr,
499162SPeter.Dunlap@Sun.COM     ib_memlen_t len, ibt_mr_flags_t mr_flags);
509162SPeter.Dunlap@Sun.COM 
519162SPeter.Dunlap@Sun.COM static void iser_dereg_mem(iser_hca_t *hca, iser_mr_t *mr);
529162SPeter.Dunlap@Sun.COM 
539162SPeter.Dunlap@Sun.COM static int iser_vmem_mr_compare(const void *void_mr1, const void *void_mr2);
549162SPeter.Dunlap@Sun.COM 
559162SPeter.Dunlap@Sun.COM /*
569162SPeter.Dunlap@Sun.COM  * iser_init_hca_caches()
579162SPeter.Dunlap@Sun.COM  * Invoked per HCA instance initialization, to establish HCA-wide
589162SPeter.Dunlap@Sun.COM  * message and buffer kmem caches. Note we'll uniquify cache names
599162SPeter.Dunlap@Sun.COM  * with the lower 32-bits of the HCA GUID.
609162SPeter.Dunlap@Sun.COM  */
619162SPeter.Dunlap@Sun.COM void
iser_init_hca_caches(iser_hca_t * hca)629162SPeter.Dunlap@Sun.COM iser_init_hca_caches(iser_hca_t *hca)
639162SPeter.Dunlap@Sun.COM {
649162SPeter.Dunlap@Sun.COM 	char name[ISER_CACHE_NAMELEN];
659162SPeter.Dunlap@Sun.COM 
669162SPeter.Dunlap@Sun.COM 	(void) snprintf(name, ISER_CACHE_NAMELEN, "iser_msg_pool_%08x",
679162SPeter.Dunlap@Sun.COM 	    (uint32_t)(hca->hca_guid & 0xFFFFFFFF));
689162SPeter.Dunlap@Sun.COM 	hca->hca_msg_pool = iser_vmem_create(name, hca, ISER_MSG_MR_CHUNKSIZE,
699162SPeter.Dunlap@Sun.COM 	    ISER_MSG_POOL_MAX, ISER_MSG_MR_FLAGS);
709162SPeter.Dunlap@Sun.COM 	(void) snprintf(name, ISER_CACHE_NAMELEN, "iser_msg_cache_%08x",
719162SPeter.Dunlap@Sun.COM 	    (uint32_t)(hca->hca_guid & 0xFFFFFFFF));
729162SPeter.Dunlap@Sun.COM 	hca->iser_msg_cache = kmem_cache_create(name, sizeof (iser_msg_t),
739162SPeter.Dunlap@Sun.COM 	    0, &iser_msg_cache_constructor, &iser_msg_cache_destructor,
749162SPeter.Dunlap@Sun.COM 	    NULL, hca, NULL, KM_SLEEP);
759162SPeter.Dunlap@Sun.COM 
769162SPeter.Dunlap@Sun.COM 	(void) snprintf(name, ISER_CACHE_NAMELEN, "iser_buf_pool_%08x",
779162SPeter.Dunlap@Sun.COM 	    (uint32_t)(hca->hca_guid & 0xFFFFFFFF));
789162SPeter.Dunlap@Sun.COM 	hca->hca_buf_pool = iser_vmem_create(name, hca, ISER_BUF_MR_CHUNKSIZE,
799162SPeter.Dunlap@Sun.COM 	    ISER_BUF_POOL_MAX, ISER_BUF_MR_FLAGS);
809162SPeter.Dunlap@Sun.COM 	(void) snprintf(name, ISER_CACHE_NAMELEN, "iser_buf_cache_%08x",
819162SPeter.Dunlap@Sun.COM 	    (uint32_t)(hca->hca_guid & 0xFFFFFFFF));
829162SPeter.Dunlap@Sun.COM 	hca->iser_buf_cache = kmem_cache_create(name, sizeof (iser_buf_t),
839162SPeter.Dunlap@Sun.COM 	    0, &iser_buf_cache_constructor, &iser_buf_cache_destructor,
849162SPeter.Dunlap@Sun.COM 	    NULL, hca, NULL, KM_SLEEP);
859162SPeter.Dunlap@Sun.COM }
869162SPeter.Dunlap@Sun.COM 
879162SPeter.Dunlap@Sun.COM /*
889162SPeter.Dunlap@Sun.COM  * iser_fini_hca_caches()
899162SPeter.Dunlap@Sun.COM  * Invoked per HCA instance teardown, this routine cleans up the
909162SPeter.Dunlap@Sun.COM  * message and buffer handle caches.
919162SPeter.Dunlap@Sun.COM  */
929162SPeter.Dunlap@Sun.COM void
iser_fini_hca_caches(iser_hca_t * hca)939162SPeter.Dunlap@Sun.COM iser_fini_hca_caches(iser_hca_t *hca)
949162SPeter.Dunlap@Sun.COM {
959162SPeter.Dunlap@Sun.COM 	kmem_cache_destroy(hca->iser_buf_cache);
969162SPeter.Dunlap@Sun.COM 	iser_vmem_destroy(hca->hca_buf_pool);
979162SPeter.Dunlap@Sun.COM 	kmem_cache_destroy(hca->iser_msg_cache);
989162SPeter.Dunlap@Sun.COM 	iser_vmem_destroy(hca->hca_msg_pool);
999162SPeter.Dunlap@Sun.COM }
1009162SPeter.Dunlap@Sun.COM 
1019162SPeter.Dunlap@Sun.COM /*
1029162SPeter.Dunlap@Sun.COM  * Allocate and initialize an iSER WR handle
1039162SPeter.Dunlap@Sun.COM  */
1049162SPeter.Dunlap@Sun.COM iser_wr_t *
iser_wr_get()1059162SPeter.Dunlap@Sun.COM iser_wr_get()
1069162SPeter.Dunlap@Sun.COM {
1079162SPeter.Dunlap@Sun.COM 	iser_wr_t	*iser_wr;
1089162SPeter.Dunlap@Sun.COM 
1099162SPeter.Dunlap@Sun.COM 	iser_wr = kmem_cache_alloc(iser_state->iser_wr_cache, KM_NOSLEEP);
1109162SPeter.Dunlap@Sun.COM 	if (iser_wr != NULL) {
1119162SPeter.Dunlap@Sun.COM 		iser_wr->iw_type = ISER_WR_UNDEFINED;
1129162SPeter.Dunlap@Sun.COM 		iser_wr->iw_msg  = NULL;
1139162SPeter.Dunlap@Sun.COM 		iser_wr->iw_buf  = NULL;
1149162SPeter.Dunlap@Sun.COM 		iser_wr->iw_pdu  = NULL;
1159162SPeter.Dunlap@Sun.COM 	}
1169162SPeter.Dunlap@Sun.COM 
1179162SPeter.Dunlap@Sun.COM 	return (iser_wr);
1189162SPeter.Dunlap@Sun.COM }
1199162SPeter.Dunlap@Sun.COM 
1209162SPeter.Dunlap@Sun.COM /*
1219162SPeter.Dunlap@Sun.COM  * Free an iSER WR handle back to the global cache
1229162SPeter.Dunlap@Sun.COM  */
1239162SPeter.Dunlap@Sun.COM void
iser_wr_free(iser_wr_t * iser_wr)1249162SPeter.Dunlap@Sun.COM iser_wr_free(iser_wr_t *iser_wr)
1259162SPeter.Dunlap@Sun.COM {
1269162SPeter.Dunlap@Sun.COM 	kmem_cache_free(iser_state->iser_wr_cache, iser_wr);
1279162SPeter.Dunlap@Sun.COM }
1289162SPeter.Dunlap@Sun.COM 
1299162SPeter.Dunlap@Sun.COM /*
1309162SPeter.Dunlap@Sun.COM  * iser_msg_cache_constructor()
1319162SPeter.Dunlap@Sun.COM  * Allocate and register memory for an iSER Control-type PDU message.
1329162SPeter.Dunlap@Sun.COM  * The cached objects will retain this memory registration in the HCA,
1339162SPeter.Dunlap@Sun.COM  * and thus provide a cache of pre-allocated and registered messages
1349162SPeter.Dunlap@Sun.COM  * for use in iSER.
1359162SPeter.Dunlap@Sun.COM  */
1369162SPeter.Dunlap@Sun.COM /* ARGSUSED */
1379162SPeter.Dunlap@Sun.COM int
iser_msg_cache_constructor(void * msg_void,void * arg,int flags)1389162SPeter.Dunlap@Sun.COM iser_msg_cache_constructor(void *msg_void, void *arg, int flags)
1399162SPeter.Dunlap@Sun.COM {
1409162SPeter.Dunlap@Sun.COM 	void		*memp = NULL;
1419162SPeter.Dunlap@Sun.COM 	int		status;
1429162SPeter.Dunlap@Sun.COM 	iser_msg_t	*msg = (iser_msg_t *)msg_void;
1439162SPeter.Dunlap@Sun.COM 	iser_hca_t	*hca = (iser_hca_t *)arg;
1449162SPeter.Dunlap@Sun.COM 	iser_mr_t	mr;
1459162SPeter.Dunlap@Sun.COM 
1469162SPeter.Dunlap@Sun.COM 	memp = iser_vmem_alloc(hca->hca_msg_pool, ISER_MAX_CTRLPDU_LEN);
1479162SPeter.Dunlap@Sun.COM 	if (memp == NULL) {
1489162SPeter.Dunlap@Sun.COM 		ISER_LOG(CE_NOTE, "iser_msg_cache_constructor: "
1499162SPeter.Dunlap@Sun.COM 		    "failed to allocate backing memory");
1509162SPeter.Dunlap@Sun.COM 		return (DDI_FAILURE);
1519162SPeter.Dunlap@Sun.COM 	}
1529162SPeter.Dunlap@Sun.COM 
1539162SPeter.Dunlap@Sun.COM 	/* Fill in iser_mr for the memory we just allocated */
1549162SPeter.Dunlap@Sun.COM 	status = iser_vmem_mr(hca->hca_msg_pool, memp,
1559162SPeter.Dunlap@Sun.COM 	    ISER_MAX_CTRLPDU_LEN, &mr);
1569162SPeter.Dunlap@Sun.COM 	if (status != IDM_STATUS_SUCCESS) {
1579162SPeter.Dunlap@Sun.COM 		ISER_LOG(CE_NOTE, "iser_msg_cache_constructor: "
1589162SPeter.Dunlap@Sun.COM 		    "couldn't find mr for %p", memp);
1599162SPeter.Dunlap@Sun.COM 		iser_vmem_free(hca->hca_msg_pool, memp, ISER_MAX_CTRLPDU_LEN);
1609162SPeter.Dunlap@Sun.COM 		return (DDI_FAILURE);
1619162SPeter.Dunlap@Sun.COM 	}
1629162SPeter.Dunlap@Sun.COM 
1639162SPeter.Dunlap@Sun.COM 	msg->msg_ds.ds_va	= (ib_vaddr_t)(uintptr_t)memp;
1649162SPeter.Dunlap@Sun.COM 	msg->msg_ds.ds_key	= mr.is_mrlkey;
1659162SPeter.Dunlap@Sun.COM 
1669162SPeter.Dunlap@Sun.COM 	/* Set a backpointer to this cache to save a lookup on free */
1679162SPeter.Dunlap@Sun.COM 	msg->cache = hca->iser_msg_cache;
1689162SPeter.Dunlap@Sun.COM 
1699162SPeter.Dunlap@Sun.COM 	return (DDI_SUCCESS);
1709162SPeter.Dunlap@Sun.COM }
1719162SPeter.Dunlap@Sun.COM 
1729162SPeter.Dunlap@Sun.COM /*
1739162SPeter.Dunlap@Sun.COM  * Deregister and free registered memory from an iser_msg_t handle.
1749162SPeter.Dunlap@Sun.COM  */
1759162SPeter.Dunlap@Sun.COM void
iser_msg_cache_destructor(void * mr,void * arg)1769162SPeter.Dunlap@Sun.COM iser_msg_cache_destructor(void *mr, void *arg)
1779162SPeter.Dunlap@Sun.COM {
1789162SPeter.Dunlap@Sun.COM 	iser_msg_t	*msg = (iser_msg_t *)mr;
1799162SPeter.Dunlap@Sun.COM 	iser_hca_t	*hca = (iser_hca_t *)arg;
1809162SPeter.Dunlap@Sun.COM 	uint8_t		*memp;
1819162SPeter.Dunlap@Sun.COM 
1829162SPeter.Dunlap@Sun.COM 	memp = (uint8_t *)(uintptr_t)(ib_vaddr_t)msg->msg_ds.ds_va;
1839162SPeter.Dunlap@Sun.COM 	iser_vmem_free(hca->hca_msg_pool, memp, ISER_MAX_CTRLPDU_LEN);
1849162SPeter.Dunlap@Sun.COM }
1859162SPeter.Dunlap@Sun.COM 
1869162SPeter.Dunlap@Sun.COM /*
1879162SPeter.Dunlap@Sun.COM  * Pull a msg handle off of hca's msg cache. If no object is available
1889162SPeter.Dunlap@Sun.COM  * on the cache, a new message buffer will be allocated and registered
1899162SPeter.Dunlap@Sun.COM  * with the HCA. Once freed, this message will not be unregistered, thus
1909162SPeter.Dunlap@Sun.COM  * building up a cache of pre-allocated and registered message buffers
1919162SPeter.Dunlap@Sun.COM  * over time.
1929162SPeter.Dunlap@Sun.COM  */
1939162SPeter.Dunlap@Sun.COM iser_msg_t *
iser_msg_get(iser_hca_t * hca,int num,int * ret)1949162SPeter.Dunlap@Sun.COM iser_msg_get(iser_hca_t *hca, int num, int *ret)
1959162SPeter.Dunlap@Sun.COM {
1969162SPeter.Dunlap@Sun.COM 	iser_msg_t	*tmp, *msg = NULL;
1979162SPeter.Dunlap@Sun.COM 	int i;
1989162SPeter.Dunlap@Sun.COM 
1999162SPeter.Dunlap@Sun.COM 	ASSERT(hca != NULL);
2009162SPeter.Dunlap@Sun.COM 
2019162SPeter.Dunlap@Sun.COM 	/*
2029162SPeter.Dunlap@Sun.COM 	 * Pull num number of message handles off the cache, linking
2039162SPeter.Dunlap@Sun.COM 	 * them if more than one have been requested.
2049162SPeter.Dunlap@Sun.COM 	 */
2059162SPeter.Dunlap@Sun.COM 	for (i = 0; i < num; i++) {
2069162SPeter.Dunlap@Sun.COM 		tmp = kmem_cache_alloc(hca->iser_msg_cache, KM_NOSLEEP);
2079162SPeter.Dunlap@Sun.COM 		if (tmp == NULL) {
2089162SPeter.Dunlap@Sun.COM 			ISER_LOG(CE_NOTE, "iser_msg_get: alloc failed, "
2099162SPeter.Dunlap@Sun.COM 			    "requested (%d) allocated (%d)", num, i);
2109162SPeter.Dunlap@Sun.COM 			break;
2119162SPeter.Dunlap@Sun.COM 		}
2129162SPeter.Dunlap@Sun.COM 		tmp->msg_ds.ds_len	= ISER_MAX_CTRLPDU_LEN;
2139162SPeter.Dunlap@Sun.COM 		tmp->nextp = msg;
2149162SPeter.Dunlap@Sun.COM 		msg = tmp;
2159162SPeter.Dunlap@Sun.COM 	}
2169162SPeter.Dunlap@Sun.COM 
2179162SPeter.Dunlap@Sun.COM 	if (ret != NULL) {
2189162SPeter.Dunlap@Sun.COM 		*ret = i;
2199162SPeter.Dunlap@Sun.COM 	}
2209162SPeter.Dunlap@Sun.COM 
2219162SPeter.Dunlap@Sun.COM 	return (msg);
2229162SPeter.Dunlap@Sun.COM }
2239162SPeter.Dunlap@Sun.COM 
2249162SPeter.Dunlap@Sun.COM /*
2259162SPeter.Dunlap@Sun.COM  * Free this msg back to its cache, leaving the memory contained by
2269162SPeter.Dunlap@Sun.COM  * it registered for later re-use.
2279162SPeter.Dunlap@Sun.COM  */
2289162SPeter.Dunlap@Sun.COM void
iser_msg_free(iser_msg_t * msg)2299162SPeter.Dunlap@Sun.COM iser_msg_free(iser_msg_t *msg)
2309162SPeter.Dunlap@Sun.COM {
2319162SPeter.Dunlap@Sun.COM 	kmem_cache_free(msg->cache, msg);
2329162SPeter.Dunlap@Sun.COM }
2339162SPeter.Dunlap@Sun.COM 
2349162SPeter.Dunlap@Sun.COM /*
2359162SPeter.Dunlap@Sun.COM  * iser_buf_cache_constructor()
2369162SPeter.Dunlap@Sun.COM  * Allocate and register memory for an iSER RDMA operation. The cached
2379162SPeter.Dunlap@Sun.COM  * objects will retain this memory registration in the HCA, and thus
2389162SPeter.Dunlap@Sun.COM  * provide a cache of pre-allocated and registered messages for use in
2399162SPeter.Dunlap@Sun.COM  * iSER.
2409162SPeter.Dunlap@Sun.COM  */
2419162SPeter.Dunlap@Sun.COM /* ARGSUSED */
2429162SPeter.Dunlap@Sun.COM int
iser_buf_cache_constructor(void * mr,void * arg,int flags)2439162SPeter.Dunlap@Sun.COM iser_buf_cache_constructor(void *mr, void *arg, int flags)
2449162SPeter.Dunlap@Sun.COM {
2459162SPeter.Dunlap@Sun.COM 	uint8_t		*memp;
2469162SPeter.Dunlap@Sun.COM 	idm_status_t	status;
2479162SPeter.Dunlap@Sun.COM 	iser_buf_t	*iser_buf = (iser_buf_t *)mr;
2489162SPeter.Dunlap@Sun.COM 	iser_hca_t	*hca = (iser_hca_t *)arg;
2499162SPeter.Dunlap@Sun.COM 
2509162SPeter.Dunlap@Sun.COM 	/* Allocate an iser_mr handle for this buffer */
2519162SPeter.Dunlap@Sun.COM 	iser_buf->iser_mr = kmem_zalloc(sizeof (iser_mr_t), KM_NOSLEEP);
2529162SPeter.Dunlap@Sun.COM 	if (iser_buf->iser_mr == NULL) {
2539162SPeter.Dunlap@Sun.COM 		ISER_LOG(CE_NOTE, "iser_buf_cache_constructor: "
2549162SPeter.Dunlap@Sun.COM 		    "failed to allocate memory for iser_mr handle");
2559162SPeter.Dunlap@Sun.COM 		return (DDI_FAILURE);
2569162SPeter.Dunlap@Sun.COM 	}
2579162SPeter.Dunlap@Sun.COM 
2589162SPeter.Dunlap@Sun.COM 	memp = iser_vmem_alloc(hca->hca_buf_pool, ISER_DEFAULT_BUFLEN);
2599162SPeter.Dunlap@Sun.COM 	if (memp == NULL) {
2609162SPeter.Dunlap@Sun.COM 		kmem_free(iser_buf->iser_mr, sizeof (iser_mr_t));
2619162SPeter.Dunlap@Sun.COM 		return (DDI_FAILURE);
2629162SPeter.Dunlap@Sun.COM 	}
2639162SPeter.Dunlap@Sun.COM 
2649162SPeter.Dunlap@Sun.COM 	/* Fill in iser_mr for the memory we just allocated */
2659162SPeter.Dunlap@Sun.COM 	status = iser_vmem_mr(hca->hca_buf_pool, memp, ISER_DEFAULT_BUFLEN,
2669162SPeter.Dunlap@Sun.COM 	    iser_buf->iser_mr);
2679162SPeter.Dunlap@Sun.COM 
2689162SPeter.Dunlap@Sun.COM 	if (status != IDM_STATUS_SUCCESS) {
2699162SPeter.Dunlap@Sun.COM 		return (DDI_FAILURE);
2709162SPeter.Dunlap@Sun.COM 	}
2719162SPeter.Dunlap@Sun.COM 
2729162SPeter.Dunlap@Sun.COM 	/* Set buf pointer and len for later manipulation (if necessary) */
2739162SPeter.Dunlap@Sun.COM 	iser_buf->buf		= (uint64_t *)(uintptr_t)memp;
2749162SPeter.Dunlap@Sun.COM 	iser_buf->buflen	= ISER_DEFAULT_BUFLEN;
2759162SPeter.Dunlap@Sun.COM 
2769162SPeter.Dunlap@Sun.COM 	/* Populate the SGE Vaddr and L_key for the xfer operation later */
2779162SPeter.Dunlap@Sun.COM 	iser_buf->buf_ds.ds_va	= iser_buf->iser_mr->is_mrva;
2789162SPeter.Dunlap@Sun.COM 	iser_buf->buf_ds.ds_key	= iser_buf->iser_mr->is_mrlkey;
2799162SPeter.Dunlap@Sun.COM 
2809162SPeter.Dunlap@Sun.COM 	/* Set a backpointer to this cache to save a lookup on free */
2819162SPeter.Dunlap@Sun.COM 	iser_buf->cache = hca->iser_buf_cache;
2829162SPeter.Dunlap@Sun.COM 
2839162SPeter.Dunlap@Sun.COM 	gethrestime(&iser_buf->buf_constructed);
2849162SPeter.Dunlap@Sun.COM 
2859162SPeter.Dunlap@Sun.COM 	return (DDI_SUCCESS);
2869162SPeter.Dunlap@Sun.COM }
2879162SPeter.Dunlap@Sun.COM 
2889162SPeter.Dunlap@Sun.COM /*
2899162SPeter.Dunlap@Sun.COM  * Deregister and free registered memory from an iser_buf_t handle.
2909162SPeter.Dunlap@Sun.COM  */
2919162SPeter.Dunlap@Sun.COM void
iser_buf_cache_destructor(void * mr,void * arg)2929162SPeter.Dunlap@Sun.COM iser_buf_cache_destructor(void *mr, void *arg)
2939162SPeter.Dunlap@Sun.COM {
2949162SPeter.Dunlap@Sun.COM 	iser_buf_t	*iser_buf = (iser_buf_t *)mr;
2959162SPeter.Dunlap@Sun.COM 	iser_hca_t	*hca = (iser_hca_t *)arg;
2969162SPeter.Dunlap@Sun.COM 
2979162SPeter.Dunlap@Sun.COM 	gethrestime(&iser_buf->buf_destructed);
2989162SPeter.Dunlap@Sun.COM 
2999162SPeter.Dunlap@Sun.COM 	iser_vmem_free(hca->hca_buf_pool, iser_buf->buf, iser_buf->buflen);
3009162SPeter.Dunlap@Sun.COM 
3019162SPeter.Dunlap@Sun.COM 	kmem_free(iser_buf->iser_mr, sizeof (iser_mr_t));
3029162SPeter.Dunlap@Sun.COM }
3039162SPeter.Dunlap@Sun.COM 
3049162SPeter.Dunlap@Sun.COM /*
3059162SPeter.Dunlap@Sun.COM  * Registration for initiator buffers
3069162SPeter.Dunlap@Sun.COM  */
3079162SPeter.Dunlap@Sun.COM int
iser_reg_rdma_mem(iser_hca_t * hca,idm_buf_t * idb)3089162SPeter.Dunlap@Sun.COM iser_reg_rdma_mem(iser_hca_t *hca, idm_buf_t *idb)
3099162SPeter.Dunlap@Sun.COM {
3109162SPeter.Dunlap@Sun.COM 	iser_mr_t	*iser_mr = NULL;
3119162SPeter.Dunlap@Sun.COM 
3129162SPeter.Dunlap@Sun.COM 	ASSERT(idb != NULL);
3139162SPeter.Dunlap@Sun.COM 	ASSERT(idb->idb_buflen > 0);
3149162SPeter.Dunlap@Sun.COM 
3159162SPeter.Dunlap@Sun.COM 	iser_mr = iser_reg_mem(hca, (ib_vaddr_t)(uintptr_t)idb->idb_buf,
3169162SPeter.Dunlap@Sun.COM 	    idb->idb_buflen, ISER_BUF_MR_FLAGS | IBT_MR_NOSLEEP);
3179162SPeter.Dunlap@Sun.COM 	if (iser_mr == NULL) {
3189162SPeter.Dunlap@Sun.COM 		ISER_LOG(CE_NOTE, "iser_reg_rdma_mem: failed to register "
3199162SPeter.Dunlap@Sun.COM 		    "memory for idm_buf_t");
3209162SPeter.Dunlap@Sun.COM 		return (DDI_FAILURE);
3219162SPeter.Dunlap@Sun.COM 	}
3229162SPeter.Dunlap@Sun.COM 
3239162SPeter.Dunlap@Sun.COM 	idb->idb_reg_private	= (void *)iser_mr;
3249162SPeter.Dunlap@Sun.COM 
3259162SPeter.Dunlap@Sun.COM 	return (DDI_SUCCESS);
3269162SPeter.Dunlap@Sun.COM }
3279162SPeter.Dunlap@Sun.COM 
3289162SPeter.Dunlap@Sun.COM void
iser_dereg_rdma_mem(iser_hca_t * hca,idm_buf_t * idb)3299162SPeter.Dunlap@Sun.COM iser_dereg_rdma_mem(iser_hca_t *hca, idm_buf_t *idb)
3309162SPeter.Dunlap@Sun.COM {
3319162SPeter.Dunlap@Sun.COM 	iser_mr_t	*mr;
3329162SPeter.Dunlap@Sun.COM 
3339162SPeter.Dunlap@Sun.COM 	ASSERT(idb != NULL);
3349162SPeter.Dunlap@Sun.COM 	mr = (iser_mr_t *)idb->idb_reg_private;
3359162SPeter.Dunlap@Sun.COM 
3369162SPeter.Dunlap@Sun.COM 	iser_dereg_mem(hca, mr);
3379162SPeter.Dunlap@Sun.COM }
3389162SPeter.Dunlap@Sun.COM 
3399162SPeter.Dunlap@Sun.COM iser_vmem_mr_pool_t *
iser_vmem_create(const char * name,iser_hca_t * hca,ib_memlen_t chunksize,uint64_t max_total_size,ibt_mr_flags_t arena_mr_flags)3409162SPeter.Dunlap@Sun.COM iser_vmem_create(const char *name, iser_hca_t *hca, ib_memlen_t chunksize,
3419162SPeter.Dunlap@Sun.COM     uint64_t max_total_size, ibt_mr_flags_t arena_mr_flags)
3429162SPeter.Dunlap@Sun.COM {
3439162SPeter.Dunlap@Sun.COM 	iser_mr_t		*first_chunk;
3449162SPeter.Dunlap@Sun.COM 	iser_vmem_mr_pool_t	*result;
3459162SPeter.Dunlap@Sun.COM 
3469162SPeter.Dunlap@Sun.COM 	ASSERT(chunksize <= max_total_size);
3479162SPeter.Dunlap@Sun.COM 	result = kmem_zalloc(sizeof (*result), KM_SLEEP);
3489162SPeter.Dunlap@Sun.COM 	result->ivmp_hca = hca;
3499162SPeter.Dunlap@Sun.COM 	result->ivmp_mr_flags = arena_mr_flags;
3509162SPeter.Dunlap@Sun.COM 	result->ivmp_chunksize = chunksize;
3519162SPeter.Dunlap@Sun.COM 	result->ivmp_max_total_size = max_total_size;
3529162SPeter.Dunlap@Sun.COM 	mutex_init(&result->ivmp_mutex, NULL, MUTEX_DRIVER, NULL);
3539162SPeter.Dunlap@Sun.COM 	avl_create(&result->ivmp_mr_list, iser_vmem_mr_compare,
3549162SPeter.Dunlap@Sun.COM 	    sizeof (iser_mr_t), offsetof(iser_mr_t, is_avl_ln));
3559162SPeter.Dunlap@Sun.COM 
3569162SPeter.Dunlap@Sun.COM 	first_chunk = iser_vmem_chunk_alloc(hca, chunksize,
3579162SPeter.Dunlap@Sun.COM 	    arena_mr_flags | IBT_MR_SLEEP);
3589162SPeter.Dunlap@Sun.COM 
3599162SPeter.Dunlap@Sun.COM 	avl_add(&result->ivmp_mr_list, first_chunk);
3609162SPeter.Dunlap@Sun.COM 	result->ivmp_total_size += chunksize;
3619162SPeter.Dunlap@Sun.COM 
3629162SPeter.Dunlap@Sun.COM 	result->ivmp_vmem = vmem_create(name,
3639162SPeter.Dunlap@Sun.COM 	    (void *)(uintptr_t)first_chunk->is_mrva,
3649162SPeter.Dunlap@Sun.COM 	    (size_t)first_chunk->is_mrlen, ISER_MR_QUANTSIZE,
3659162SPeter.Dunlap@Sun.COM 	    NULL, NULL, NULL, 0, VM_SLEEP);
3669162SPeter.Dunlap@Sun.COM 
3679162SPeter.Dunlap@Sun.COM 	return (result);
3689162SPeter.Dunlap@Sun.COM }
3699162SPeter.Dunlap@Sun.COM 
3709162SPeter.Dunlap@Sun.COM void
iser_vmem_destroy(iser_vmem_mr_pool_t * vmr_pool)3719162SPeter.Dunlap@Sun.COM iser_vmem_destroy(iser_vmem_mr_pool_t *vmr_pool)
3729162SPeter.Dunlap@Sun.COM {
3739162SPeter.Dunlap@Sun.COM 	iser_mr_t	*chunk, *next_chunk;
3749162SPeter.Dunlap@Sun.COM 
3759162SPeter.Dunlap@Sun.COM 	mutex_enter(&vmr_pool->ivmp_mutex);
3769162SPeter.Dunlap@Sun.COM 	vmem_destroy(vmr_pool->ivmp_vmem);
3779162SPeter.Dunlap@Sun.COM 
3789162SPeter.Dunlap@Sun.COM 	for (chunk = avl_first(&vmr_pool->ivmp_mr_list); chunk != NULL;
3799162SPeter.Dunlap@Sun.COM 	    chunk = next_chunk) {
3809162SPeter.Dunlap@Sun.COM 		next_chunk = AVL_NEXT(&vmr_pool->ivmp_mr_list, chunk);
3819162SPeter.Dunlap@Sun.COM 		avl_remove(&vmr_pool->ivmp_mr_list, chunk);
3829162SPeter.Dunlap@Sun.COM 		iser_vmem_chunk_free(vmr_pool->ivmp_hca, chunk);
3839162SPeter.Dunlap@Sun.COM 	}
3849162SPeter.Dunlap@Sun.COM 	mutex_exit(&vmr_pool->ivmp_mutex);
3859162SPeter.Dunlap@Sun.COM 
3869162SPeter.Dunlap@Sun.COM 	avl_destroy(&vmr_pool->ivmp_mr_list);
3879162SPeter.Dunlap@Sun.COM 	mutex_destroy(&vmr_pool->ivmp_mutex);
3889162SPeter.Dunlap@Sun.COM 
3899162SPeter.Dunlap@Sun.COM 	kmem_free(vmr_pool, sizeof (*vmr_pool));
3909162SPeter.Dunlap@Sun.COM }
3919162SPeter.Dunlap@Sun.COM 
3929162SPeter.Dunlap@Sun.COM void *
iser_vmem_alloc(iser_vmem_mr_pool_t * vmr_pool,size_t size)3939162SPeter.Dunlap@Sun.COM iser_vmem_alloc(iser_vmem_mr_pool_t *vmr_pool, size_t size)
3949162SPeter.Dunlap@Sun.COM {
3959162SPeter.Dunlap@Sun.COM 	void		*result;
3969162SPeter.Dunlap@Sun.COM 	iser_mr_t	*next_chunk;
3979162SPeter.Dunlap@Sun.COM 	ib_memlen_t	chunk_len;
3989162SPeter.Dunlap@Sun.COM 	result = vmem_alloc(vmr_pool->ivmp_vmem, size,
3999162SPeter.Dunlap@Sun.COM 	    VM_NOSLEEP | VM_FIRSTFIT);
4009162SPeter.Dunlap@Sun.COM 	if (result == NULL) {
4019162SPeter.Dunlap@Sun.COM 		mutex_enter(&vmr_pool->ivmp_mutex);
4029162SPeter.Dunlap@Sun.COM 		chunk_len = vmr_pool->ivmp_chunksize;
4039162SPeter.Dunlap@Sun.COM 		if ((vmr_pool->ivmp_total_size + chunk_len) >
4049162SPeter.Dunlap@Sun.COM 		    vmr_pool->ivmp_max_total_size) {
4059162SPeter.Dunlap@Sun.COM 			/*
4069162SPeter.Dunlap@Sun.COM 			 * Don't go over the pool size limit.  We can allocate
4079162SPeter.Dunlap@Sun.COM 			 * partial chunks so it's not always the case that
4089162SPeter.Dunlap@Sun.COM 			 * current_size + chunk_size == max_total_size
4099162SPeter.Dunlap@Sun.COM 			 */
4109162SPeter.Dunlap@Sun.COM 			if (vmr_pool->ivmp_total_size >=
4119162SPeter.Dunlap@Sun.COM 			    vmr_pool->ivmp_max_total_size) {
4129162SPeter.Dunlap@Sun.COM 				mutex_exit(&vmr_pool->ivmp_mutex);
4139162SPeter.Dunlap@Sun.COM 				return (NULL);
4149162SPeter.Dunlap@Sun.COM 			} else {
4159162SPeter.Dunlap@Sun.COM 				chunk_len = vmr_pool->ivmp_max_total_size -
4169162SPeter.Dunlap@Sun.COM 				    vmr_pool->ivmp_total_size;
4179162SPeter.Dunlap@Sun.COM 			}
4189162SPeter.Dunlap@Sun.COM 		}
4199162SPeter.Dunlap@Sun.COM 		next_chunk = iser_vmem_chunk_alloc(vmr_pool->ivmp_hca,
4209162SPeter.Dunlap@Sun.COM 		    chunk_len, vmr_pool->ivmp_mr_flags | IBT_MR_NOSLEEP);
4219162SPeter.Dunlap@Sun.COM 		if (next_chunk != NULL) {
4229162SPeter.Dunlap@Sun.COM 			if (vmem_add(vmr_pool->ivmp_vmem,
4239162SPeter.Dunlap@Sun.COM 			    (void *)(uintptr_t)next_chunk->is_mrva,
4249162SPeter.Dunlap@Sun.COM 			    next_chunk->is_mrlen, VM_NOSLEEP) == NULL) {
4259162SPeter.Dunlap@Sun.COM 				/* Free the chunk we just allocated */
4269162SPeter.Dunlap@Sun.COM 				iser_vmem_chunk_free(vmr_pool->ivmp_hca,
4279162SPeter.Dunlap@Sun.COM 				    next_chunk);
4289162SPeter.Dunlap@Sun.COM 			} else {
4299162SPeter.Dunlap@Sun.COM 				vmr_pool->ivmp_total_size +=
4309162SPeter.Dunlap@Sun.COM 				    next_chunk->is_mrlen;
4319162SPeter.Dunlap@Sun.COM 				avl_add(&vmr_pool->ivmp_mr_list, next_chunk);
4329162SPeter.Dunlap@Sun.COM 			}
4339162SPeter.Dunlap@Sun.COM 
4349162SPeter.Dunlap@Sun.COM 			result = vmem_alloc(vmr_pool->ivmp_vmem, size,
4359162SPeter.Dunlap@Sun.COM 			    VM_NOSLEEP | VM_FIRSTFIT);
4369162SPeter.Dunlap@Sun.COM 		}
4379162SPeter.Dunlap@Sun.COM 
4389162SPeter.Dunlap@Sun.COM 		mutex_exit(&vmr_pool->ivmp_mutex);
4399162SPeter.Dunlap@Sun.COM 	}
4409162SPeter.Dunlap@Sun.COM 
4419162SPeter.Dunlap@Sun.COM 	return (result);
4429162SPeter.Dunlap@Sun.COM }
4439162SPeter.Dunlap@Sun.COM 
4449162SPeter.Dunlap@Sun.COM 
4459162SPeter.Dunlap@Sun.COM void
iser_vmem_free(iser_vmem_mr_pool_t * vmr_pool,void * vaddr,size_t size)4469162SPeter.Dunlap@Sun.COM iser_vmem_free(iser_vmem_mr_pool_t *vmr_pool, void *vaddr, size_t size)
4479162SPeter.Dunlap@Sun.COM {
4489162SPeter.Dunlap@Sun.COM 	vmem_free(vmr_pool->ivmp_vmem, vaddr, size);
4499162SPeter.Dunlap@Sun.COM }
4509162SPeter.Dunlap@Sun.COM 
4519162SPeter.Dunlap@Sun.COM idm_status_t
iser_vmem_mr(iser_vmem_mr_pool_t * vmr_pool,void * vaddr,size_t size,iser_mr_t * mr)4529162SPeter.Dunlap@Sun.COM iser_vmem_mr(iser_vmem_mr_pool_t *vmr_pool, void *vaddr, size_t size,
4539162SPeter.Dunlap@Sun.COM     iser_mr_t *mr)
4549162SPeter.Dunlap@Sun.COM {
4559162SPeter.Dunlap@Sun.COM 	avl_index_t	where;
4569162SPeter.Dunlap@Sun.COM 	ib_vaddr_t	mrva = (ib_vaddr_t)(uintptr_t)vaddr;
4579162SPeter.Dunlap@Sun.COM 	iser_mr_t	search_chunk;
4589162SPeter.Dunlap@Sun.COM 	iser_mr_t	*nearest_chunk;
4599162SPeter.Dunlap@Sun.COM 	ib_vaddr_t	chunk_end;
4609162SPeter.Dunlap@Sun.COM 
4619162SPeter.Dunlap@Sun.COM 	mutex_enter(&vmr_pool->ivmp_mutex);
4629162SPeter.Dunlap@Sun.COM 	search_chunk.is_mrva = mrva;
4639162SPeter.Dunlap@Sun.COM 	nearest_chunk = avl_find(&vmr_pool->ivmp_mr_list, &search_chunk,
4649162SPeter.Dunlap@Sun.COM 	    &where);
4659162SPeter.Dunlap@Sun.COM 	if (nearest_chunk == NULL) {
4669162SPeter.Dunlap@Sun.COM 		nearest_chunk = avl_nearest(&vmr_pool->ivmp_mr_list, where,
4679162SPeter.Dunlap@Sun.COM 		    AVL_BEFORE);
4689162SPeter.Dunlap@Sun.COM 		if (nearest_chunk == NULL) {
4699162SPeter.Dunlap@Sun.COM 			mutex_exit(&vmr_pool->ivmp_mutex);
4709162SPeter.Dunlap@Sun.COM 			return (IDM_STATUS_FAIL);
4719162SPeter.Dunlap@Sun.COM 		}
4729162SPeter.Dunlap@Sun.COM 	}
4739162SPeter.Dunlap@Sun.COM 
4749162SPeter.Dunlap@Sun.COM 	/* See if this chunk contains the specified address range */
4759162SPeter.Dunlap@Sun.COM 	ASSERT(nearest_chunk->is_mrva <= mrva);
4769162SPeter.Dunlap@Sun.COM 	chunk_end = nearest_chunk->is_mrva + nearest_chunk->is_mrlen;
4779162SPeter.Dunlap@Sun.COM 	if (chunk_end >= mrva + size) {
4789162SPeter.Dunlap@Sun.COM 		/* Yes, this chunk contains the address range */
4799162SPeter.Dunlap@Sun.COM 		mr->is_mrhdl = nearest_chunk->is_mrhdl;
4809162SPeter.Dunlap@Sun.COM 		mr->is_mrva = mrva;
4819162SPeter.Dunlap@Sun.COM 		mr->is_mrlen = size;
4829162SPeter.Dunlap@Sun.COM 		mr->is_mrlkey = nearest_chunk->is_mrlkey;
4839162SPeter.Dunlap@Sun.COM 		mr->is_mrrkey = nearest_chunk->is_mrrkey;
4849162SPeter.Dunlap@Sun.COM 		mutex_exit(&vmr_pool->ivmp_mutex);
4859162SPeter.Dunlap@Sun.COM 		return (IDM_STATUS_SUCCESS);
4869162SPeter.Dunlap@Sun.COM 	}
4879162SPeter.Dunlap@Sun.COM 	mutex_exit(&vmr_pool->ivmp_mutex);
4889162SPeter.Dunlap@Sun.COM 
4899162SPeter.Dunlap@Sun.COM 	return (IDM_STATUS_FAIL);
4909162SPeter.Dunlap@Sun.COM }
4919162SPeter.Dunlap@Sun.COM 
4929162SPeter.Dunlap@Sun.COM static iser_mr_t *
iser_vmem_chunk_alloc(iser_hca_t * hca,ib_memlen_t chunksize,ibt_mr_flags_t mr_flags)4939162SPeter.Dunlap@Sun.COM iser_vmem_chunk_alloc(iser_hca_t *hca, ib_memlen_t chunksize,
4949162SPeter.Dunlap@Sun.COM     ibt_mr_flags_t mr_flags)
4959162SPeter.Dunlap@Sun.COM {
4969162SPeter.Dunlap@Sun.COM 	void		*chunk = NULL;
4979162SPeter.Dunlap@Sun.COM 	iser_mr_t	*result = NULL;
4989162SPeter.Dunlap@Sun.COM 	int		km_flags = 0;
4999162SPeter.Dunlap@Sun.COM 
5009162SPeter.Dunlap@Sun.COM 	if (mr_flags & IBT_MR_NOSLEEP)
5019162SPeter.Dunlap@Sun.COM 		km_flags |= KM_NOSLEEP;
5029162SPeter.Dunlap@Sun.COM 
5039162SPeter.Dunlap@Sun.COM 	while ((chunk == NULL) && (chunksize >= ISER_MIN_CHUNKSIZE)) {
5049162SPeter.Dunlap@Sun.COM 		chunk = kmem_alloc(chunksize, km_flags);
5059162SPeter.Dunlap@Sun.COM 		if (chunk == NULL) {
5069162SPeter.Dunlap@Sun.COM 			ISER_LOG(CE_NOTE, "iser_vmem_chunk_alloc: "
5079162SPeter.Dunlap@Sun.COM 			    "chunk alloc of %d failed, trying %d",
5089162SPeter.Dunlap@Sun.COM 			    (int)chunksize, (int)(chunksize / 2));
5099162SPeter.Dunlap@Sun.COM 			chunksize /= 2;
5109162SPeter.Dunlap@Sun.COM 		} else {
5119162SPeter.Dunlap@Sun.COM 			ISER_LOG(CE_NOTE, "iser_vmem_chunk_alloc: "
5129162SPeter.Dunlap@Sun.COM 			    "New chunk %p size %d", chunk, (int)chunksize);
5139162SPeter.Dunlap@Sun.COM 		}
5149162SPeter.Dunlap@Sun.COM 	}
5159162SPeter.Dunlap@Sun.COM 
5169162SPeter.Dunlap@Sun.COM 	if (chunk != NULL) {
5179162SPeter.Dunlap@Sun.COM 		result = iser_reg_mem(hca, (ib_vaddr_t)(uintptr_t)chunk,
5189162SPeter.Dunlap@Sun.COM 		    chunksize, mr_flags);
5199162SPeter.Dunlap@Sun.COM 		if (result == NULL) {
5209162SPeter.Dunlap@Sun.COM 			ISER_LOG(CE_NOTE, "iser_vmem_chunk_alloc: "
5219162SPeter.Dunlap@Sun.COM 			    "Chunk registration failed");
5229162SPeter.Dunlap@Sun.COM 			kmem_free(chunk, chunksize);
5239162SPeter.Dunlap@Sun.COM 		}
5249162SPeter.Dunlap@Sun.COM 	}
5259162SPeter.Dunlap@Sun.COM 
5269162SPeter.Dunlap@Sun.COM 	return (result);
5279162SPeter.Dunlap@Sun.COM }
5289162SPeter.Dunlap@Sun.COM 
5299162SPeter.Dunlap@Sun.COM static void
iser_vmem_chunk_free(iser_hca_t * hca,iser_mr_t * iser_mr)5309162SPeter.Dunlap@Sun.COM iser_vmem_chunk_free(iser_hca_t *hca, iser_mr_t *iser_mr)
5319162SPeter.Dunlap@Sun.COM {
5329162SPeter.Dunlap@Sun.COM 	void		*chunk		= (void *)(uintptr_t)iser_mr->is_mrva;
5339162SPeter.Dunlap@Sun.COM 	ib_memlen_t	chunksize	= iser_mr->is_mrlen;
5349162SPeter.Dunlap@Sun.COM 
5359162SPeter.Dunlap@Sun.COM 	iser_dereg_mem(hca, iser_mr);
5369162SPeter.Dunlap@Sun.COM 
5379162SPeter.Dunlap@Sun.COM 	kmem_free(chunk, chunksize);
5389162SPeter.Dunlap@Sun.COM }
5399162SPeter.Dunlap@Sun.COM 
5409162SPeter.Dunlap@Sun.COM iser_mr_t *
iser_reg_mem(iser_hca_t * hca,ib_vaddr_t vaddr,ib_memlen_t len,ibt_mr_flags_t mr_flags)5419162SPeter.Dunlap@Sun.COM iser_reg_mem(iser_hca_t *hca, ib_vaddr_t vaddr, ib_memlen_t len,
5429162SPeter.Dunlap@Sun.COM     ibt_mr_flags_t mr_flags)
5439162SPeter.Dunlap@Sun.COM {
5449162SPeter.Dunlap@Sun.COM 	iser_mr_t	*result = NULL;
5459162SPeter.Dunlap@Sun.COM 	ibt_mr_attr_t   mr_attr;
5469162SPeter.Dunlap@Sun.COM 	ibt_mr_desc_t	mr_desc;
5479162SPeter.Dunlap@Sun.COM 	ibt_status_t	status;
5489162SPeter.Dunlap@Sun.COM 	int		km_flags = 0;
5499162SPeter.Dunlap@Sun.COM 
5509162SPeter.Dunlap@Sun.COM 	if (mr_flags & IBT_MR_NOSLEEP)
5519162SPeter.Dunlap@Sun.COM 		mr_flags |= KM_NOSLEEP;
5529162SPeter.Dunlap@Sun.COM 
5539162SPeter.Dunlap@Sun.COM 	result = (iser_mr_t *)kmem_zalloc(sizeof (iser_mr_t), km_flags);
5549162SPeter.Dunlap@Sun.COM 	if (result == NULL) {
5559162SPeter.Dunlap@Sun.COM 		ISER_LOG(CE_NOTE, "iser_reg_mem: failed to allocate "
5569162SPeter.Dunlap@Sun.COM 		    "memory for iser_mr handle");
5579162SPeter.Dunlap@Sun.COM 		return (NULL);
5589162SPeter.Dunlap@Sun.COM 	}
5599162SPeter.Dunlap@Sun.COM 
5609162SPeter.Dunlap@Sun.COM 	bzero(&mr_attr, sizeof (ibt_mr_attr_t));
5619162SPeter.Dunlap@Sun.COM 	bzero(&mr_desc, sizeof (ibt_mr_desc_t));
5629162SPeter.Dunlap@Sun.COM 
5639162SPeter.Dunlap@Sun.COM 	mr_attr.mr_vaddr	= vaddr;
5649162SPeter.Dunlap@Sun.COM 	mr_attr.mr_len		= len;
5659162SPeter.Dunlap@Sun.COM 	mr_attr.mr_as		= NULL;
5669162SPeter.Dunlap@Sun.COM 	mr_attr.mr_flags	= mr_flags;
5679162SPeter.Dunlap@Sun.COM 
5689162SPeter.Dunlap@Sun.COM 	status = ibt_register_mr(hca->hca_hdl, hca->hca_pdhdl, &mr_attr,
5699162SPeter.Dunlap@Sun.COM 	    &result->is_mrhdl, &mr_desc);
5709162SPeter.Dunlap@Sun.COM 	if (status != IBT_SUCCESS) {
5719162SPeter.Dunlap@Sun.COM 		ISER_LOG(CE_NOTE, "iser_reg_mem: ibt_register_mr "
5729162SPeter.Dunlap@Sun.COM 		    "failure (%d)", status);
5739162SPeter.Dunlap@Sun.COM 		kmem_free(result, sizeof (iser_mr_t));
5749162SPeter.Dunlap@Sun.COM 		return (NULL);
5759162SPeter.Dunlap@Sun.COM 	}
5769162SPeter.Dunlap@Sun.COM 
5779162SPeter.Dunlap@Sun.COM 	result->is_mrva		= mr_attr.mr_vaddr;
5789162SPeter.Dunlap@Sun.COM 	result->is_mrlen	= mr_attr.mr_len;
5799162SPeter.Dunlap@Sun.COM 	result->is_mrlkey	= mr_desc.md_lkey;
5809162SPeter.Dunlap@Sun.COM 	result->is_mrrkey	= mr_desc.md_rkey;
5819162SPeter.Dunlap@Sun.COM 
5829162SPeter.Dunlap@Sun.COM 	return (result);
5839162SPeter.Dunlap@Sun.COM }
5849162SPeter.Dunlap@Sun.COM 
5859162SPeter.Dunlap@Sun.COM void
iser_dereg_mem(iser_hca_t * hca,iser_mr_t * mr)5869162SPeter.Dunlap@Sun.COM iser_dereg_mem(iser_hca_t *hca, iser_mr_t *mr)
5879162SPeter.Dunlap@Sun.COM {
588*11093SSrivijitha.Dugganapalli@Sun.COM 	(void) ibt_deregister_mr(hca->hca_hdl, mr->is_mrhdl);
5899162SPeter.Dunlap@Sun.COM 	kmem_free(mr, sizeof (iser_mr_t));
5909162SPeter.Dunlap@Sun.COM }
5919162SPeter.Dunlap@Sun.COM 
5929162SPeter.Dunlap@Sun.COM static int
iser_vmem_mr_compare(const void * void_mr1,const void * void_mr2)5939162SPeter.Dunlap@Sun.COM iser_vmem_mr_compare(const void *void_mr1, const void *void_mr2)
5949162SPeter.Dunlap@Sun.COM {
5959162SPeter.Dunlap@Sun.COM 	iser_mr_t *mr1 = (iser_mr_t *)void_mr1;
5969162SPeter.Dunlap@Sun.COM 	iser_mr_t *mr2 = (iser_mr_t *)void_mr2;
5979162SPeter.Dunlap@Sun.COM 
5989162SPeter.Dunlap@Sun.COM 	/* Sort memory chunks by their virtual address */
5999162SPeter.Dunlap@Sun.COM 	if (mr1->is_mrva < mr2->is_mrva)
6009162SPeter.Dunlap@Sun.COM 		return (-1);
6019162SPeter.Dunlap@Sun.COM 	else if (mr1->is_mrva > mr2->is_mrva)
6029162SPeter.Dunlap@Sun.COM 		return (1);
6039162SPeter.Dunlap@Sun.COM 
6049162SPeter.Dunlap@Sun.COM 	return (0);
6059162SPeter.Dunlap@Sun.COM }
606