10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57387SRobert.Gordon@Sun.COM  * Common Development and Distribution License (the "License").
67387SRobert.Gordon@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*8695SRajkumar.Sivaprakasam@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
267387SRobert.Gordon@Sun.COM /*
27*8695SRajkumar.Sivaprakasam@Sun.COM  * Copyright (c) 2008, The Ohio State University. All rights reserved.
287387SRobert.Gordon@Sun.COM  *
297387SRobert.Gordon@Sun.COM  * Portions of this source code is developed by the team members of
307387SRobert.Gordon@Sun.COM  * The Ohio State University's Network-Based Computing Laboratory (NBCL),
317387SRobert.Gordon@Sun.COM  * headed by Professor Dhabaleswar K. (DK) Panda.
327387SRobert.Gordon@Sun.COM  *
337387SRobert.Gordon@Sun.COM  * Acknowledgements to contributions from developors:
347387SRobert.Gordon@Sun.COM  *   Ranjit Noronha: noronha@cse.ohio-state.edu
357387SRobert.Gordon@Sun.COM  *   Lei Chai      : chail@cse.ohio-state.edu
367387SRobert.Gordon@Sun.COM  *   Weikuan Yu    : yuw@cse.ohio-state.edu
377387SRobert.Gordon@Sun.COM  *
387387SRobert.Gordon@Sun.COM  */
390Sstevel@tonic-gate 
400Sstevel@tonic-gate #include <sys/systm.h>
410Sstevel@tonic-gate #include <sys/kstat.h>
420Sstevel@tonic-gate #include <sys/modctl.h>
437387SRobert.Gordon@Sun.COM #include <sys/sdt.h>
440Sstevel@tonic-gate #include <rpc/rpc_rdma.h>
450Sstevel@tonic-gate 
460Sstevel@tonic-gate #include <sys/ib/ibtl/ibti.h>
470Sstevel@tonic-gate 
480Sstevel@tonic-gate uint_t rdma_minchunk = RDMA_MINCHUNK;
490Sstevel@tonic-gate 
500Sstevel@tonic-gate /*
510Sstevel@tonic-gate  * Globals
520Sstevel@tonic-gate  */
530Sstevel@tonic-gate int rdma_modloaded = 0;		/* flag to load RDMA plugin modules */
540Sstevel@tonic-gate int rdma_dev_available = 0;	/* if any RDMA device is loaded */
550Sstevel@tonic-gate kmutex_t rdma_modload_lock;	/* protects rdma_modloaded flag */
56*8695SRajkumar.Sivaprakasam@Sun.COM 
57*8695SRajkumar.Sivaprakasam@Sun.COM rdma_svc_wait_t rdma_wait;
58*8695SRajkumar.Sivaprakasam@Sun.COM 
590Sstevel@tonic-gate rdma_registry_t	*rdma_mod_head = NULL;	/* head for RDMA modules */
600Sstevel@tonic-gate krwlock_t	rdma_lock;		/* protects rdma_mod_head list */
610Sstevel@tonic-gate ldi_ident_t rpcmod_li = NULL;	/* identifies us with ldi_ framework */
620Sstevel@tonic-gate 
637387SRobert.Gordon@Sun.COM kmem_cache_t *clist_cache = NULL;
647387SRobert.Gordon@Sun.COM 
650Sstevel@tonic-gate /*
660Sstevel@tonic-gate  * Statics
670Sstevel@tonic-gate  */
68*8695SRajkumar.Sivaprakasam@Sun.COM ldi_handle_t rpcib_handle = NULL;
690Sstevel@tonic-gate 
700Sstevel@tonic-gate /*
710Sstevel@tonic-gate  * Externs
720Sstevel@tonic-gate  */
730Sstevel@tonic-gate extern	kstat_named_t	*rdmarcstat_ptr;
740Sstevel@tonic-gate extern	uint_t		rdmarcstat_ndata;
750Sstevel@tonic-gate extern	kstat_named_t	*rdmarsstat_ptr;
760Sstevel@tonic-gate extern	uint_t		rdmarsstat_ndata;
770Sstevel@tonic-gate 
780Sstevel@tonic-gate void rdma_kstat_init();
790Sstevel@tonic-gate 
800Sstevel@tonic-gate /*
810Sstevel@tonic-gate  * RDMATF module registration routine.
820Sstevel@tonic-gate  * This routine is expected to be called by the init routine in
830Sstevel@tonic-gate  * the plugin modules.
840Sstevel@tonic-gate  */
850Sstevel@tonic-gate rdma_stat
860Sstevel@tonic-gate rdma_register_mod(rdma_mod_t *mod)
870Sstevel@tonic-gate {
880Sstevel@tonic-gate 	rdma_registry_t **mp, *m;
890Sstevel@tonic-gate 
900Sstevel@tonic-gate 	if (mod->rdma_version != RDMATF_VERS) {
910Sstevel@tonic-gate 		return (RDMA_BADVERS);
920Sstevel@tonic-gate 	}
930Sstevel@tonic-gate 
940Sstevel@tonic-gate 	rw_enter(&rdma_lock, RW_WRITER);
950Sstevel@tonic-gate 	/*
960Sstevel@tonic-gate 	 * Ensure not already registered
970Sstevel@tonic-gate 	 */
980Sstevel@tonic-gate 	mp = &rdma_mod_head;
990Sstevel@tonic-gate 	while (*mp != NULL) {
1000Sstevel@tonic-gate 		if (strncmp((*mp)->r_mod->rdma_api, mod->rdma_api,
1010Sstevel@tonic-gate 		    KNC_STRSIZE) == 0) {
102*8695SRajkumar.Sivaprakasam@Sun.COM 			if ((*mp)->r_mod_state == RDMA_MOD_INACTIVE) {
103*8695SRajkumar.Sivaprakasam@Sun.COM 				(*mp)->r_mod_state = RDMA_MOD_ACTIVE;
104*8695SRajkumar.Sivaprakasam@Sun.COM 				(*mp)->r_mod->rdma_ops = mod->rdma_ops;
105*8695SRajkumar.Sivaprakasam@Sun.COM 				(*mp)->r_mod->rdma_count = mod->rdma_count;
106*8695SRajkumar.Sivaprakasam@Sun.COM 				goto announce_hca;
107*8695SRajkumar.Sivaprakasam@Sun.COM 			}
1080Sstevel@tonic-gate 			rw_exit(&rdma_lock);
1090Sstevel@tonic-gate 			return (RDMA_REG_EXIST);
1100Sstevel@tonic-gate 		}
1110Sstevel@tonic-gate 		mp = &((*mp)->r_next);
1120Sstevel@tonic-gate 	}
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate 	/*
1150Sstevel@tonic-gate 	 * New one, create and add to registry
1160Sstevel@tonic-gate 	 */
1170Sstevel@tonic-gate 	m = kmem_alloc(sizeof (rdma_registry_t), KM_SLEEP);
1180Sstevel@tonic-gate 	m->r_mod = kmem_alloc(sizeof (rdma_mod_t), KM_SLEEP);
1190Sstevel@tonic-gate 	*m->r_mod = *mod;
1200Sstevel@tonic-gate 	m->r_next = NULL;
1210Sstevel@tonic-gate 	m->r_mod->rdma_api = kmem_zalloc(KNC_STRSIZE, KM_SLEEP);
1220Sstevel@tonic-gate 	(void) strncpy(m->r_mod->rdma_api, mod->rdma_api, KNC_STRSIZE);
1230Sstevel@tonic-gate 	m->r_mod->rdma_api[KNC_STRSIZE - 1] = '\0';
124*8695SRajkumar.Sivaprakasam@Sun.COM 	m->r_mod_state = RDMA_MOD_ACTIVE;
1250Sstevel@tonic-gate 	*mp = m;
126*8695SRajkumar.Sivaprakasam@Sun.COM 
127*8695SRajkumar.Sivaprakasam@Sun.COM announce_hca:
1280Sstevel@tonic-gate 	rw_exit(&rdma_lock);
129*8695SRajkumar.Sivaprakasam@Sun.COM 	/*
130*8695SRajkumar.Sivaprakasam@Sun.COM 	 * Start the nfs service on the rdma xprts.
131*8695SRajkumar.Sivaprakasam@Sun.COM 	 * (this notification mechanism will need to change when we support
132*8695SRajkumar.Sivaprakasam@Sun.COM 	 * multiple hcas and have support for multiple rdma plugins).
133*8695SRajkumar.Sivaprakasam@Sun.COM 	 */
134*8695SRajkumar.Sivaprakasam@Sun.COM 	mutex_enter(&rdma_wait.svc_lock);
135*8695SRajkumar.Sivaprakasam@Sun.COM 	rdma_wait.svc_stat = RDMA_HCA_ATTACH;
136*8695SRajkumar.Sivaprakasam@Sun.COM 	cv_signal(&rdma_wait.svc_cv);
137*8695SRajkumar.Sivaprakasam@Sun.COM 	mutex_exit(&rdma_wait.svc_lock);
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 	return (RDMA_SUCCESS);
1400Sstevel@tonic-gate }
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate /*
1430Sstevel@tonic-gate  * RDMATF module unregistration routine.
1440Sstevel@tonic-gate  * This routine is expected to be called by the fini routine in
1450Sstevel@tonic-gate  * the plugin modules.
1460Sstevel@tonic-gate  */
1470Sstevel@tonic-gate rdma_stat
1480Sstevel@tonic-gate rdma_unregister_mod(rdma_mod_t *mod)
1490Sstevel@tonic-gate {
1500Sstevel@tonic-gate 	rdma_registry_t **m, *mmod = NULL;
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate 	rw_enter(&rdma_lock, RW_WRITER);
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	m = &rdma_mod_head;
1550Sstevel@tonic-gate 	while (*m != NULL) {
1560Sstevel@tonic-gate 		if (strncmp((*m)->r_mod->rdma_api, mod->rdma_api,
1570Sstevel@tonic-gate 		    KNC_STRSIZE) != 0) {
1580Sstevel@tonic-gate 			m = &((*m)->r_next);
1590Sstevel@tonic-gate 			continue;
1600Sstevel@tonic-gate 		}
1610Sstevel@tonic-gate 		/*
1620Sstevel@tonic-gate 		 * Check if any device attached, if so return error
1630Sstevel@tonic-gate 		 */
164*8695SRajkumar.Sivaprakasam@Sun.COM 		if (mod->rdma_count != 0) {
1650Sstevel@tonic-gate 			rw_exit(&rdma_lock);
1660Sstevel@tonic-gate 			return (RDMA_FAILED);
1670Sstevel@tonic-gate 		}
1680Sstevel@tonic-gate 		/*
169*8695SRajkumar.Sivaprakasam@Sun.COM 		 * Found entry. Mark it inactive.
1700Sstevel@tonic-gate 		 */
1710Sstevel@tonic-gate 		mmod = *m;
172*8695SRajkumar.Sivaprakasam@Sun.COM 		mmod->r_mod->rdma_count = 0;
173*8695SRajkumar.Sivaprakasam@Sun.COM 		mmod->r_mod_state = RDMA_MOD_INACTIVE;
174*8695SRajkumar.Sivaprakasam@Sun.COM 		break;
1750Sstevel@tonic-gate 	}
1760Sstevel@tonic-gate 
177*8695SRajkumar.Sivaprakasam@Sun.COM 	rdma_modloaded = 0;
178*8695SRajkumar.Sivaprakasam@Sun.COM 	rdma_dev_available = 0;
179*8695SRajkumar.Sivaprakasam@Sun.COM 	rw_exit(&rdma_lock);
180*8695SRajkumar.Sivaprakasam@Sun.COM 
181*8695SRajkumar.Sivaprakasam@Sun.COM 	/*
182*8695SRajkumar.Sivaprakasam@Sun.COM 	 * Stop the nfs service running on the rdma xprts.
183*8695SRajkumar.Sivaprakasam@Sun.COM 	 * (this notification mechanism will need to change when we support
184*8695SRajkumar.Sivaprakasam@Sun.COM 	 * multiple hcas and have support for multiple rdma plugins).
185*8695SRajkumar.Sivaprakasam@Sun.COM 	 */
186*8695SRajkumar.Sivaprakasam@Sun.COM 	mutex_enter(&rdma_wait.svc_lock);
187*8695SRajkumar.Sivaprakasam@Sun.COM 	rdma_wait.svc_stat = RDMA_HCA_DETACH;
188*8695SRajkumar.Sivaprakasam@Sun.COM 	cv_signal(&rdma_wait.svc_cv);
189*8695SRajkumar.Sivaprakasam@Sun.COM 	mutex_exit(&rdma_wait.svc_lock);
190*8695SRajkumar.Sivaprakasam@Sun.COM 
1910Sstevel@tonic-gate 	/*
1920Sstevel@tonic-gate 	 * Not found.
1930Sstevel@tonic-gate 	 */
194*8695SRajkumar.Sivaprakasam@Sun.COM 	return (RDMA_SUCCESS);
1950Sstevel@tonic-gate }
1960Sstevel@tonic-gate 
1977387SRobert.Gordon@Sun.COM struct clist *
1987387SRobert.Gordon@Sun.COM clist_alloc(void)
1997387SRobert.Gordon@Sun.COM {
2007387SRobert.Gordon@Sun.COM 	struct clist *clp;
2017387SRobert.Gordon@Sun.COM 
2027387SRobert.Gordon@Sun.COM 	clp = kmem_cache_alloc(clist_cache, KM_SLEEP);
2037387SRobert.Gordon@Sun.COM 
2047387SRobert.Gordon@Sun.COM 	bzero(clp, sizeof (*clp));
2057387SRobert.Gordon@Sun.COM 
2067387SRobert.Gordon@Sun.COM 	return (clp);
2077387SRobert.Gordon@Sun.COM }
2087387SRobert.Gordon@Sun.COM 
2090Sstevel@tonic-gate /*
2100Sstevel@tonic-gate  * Creates a new chunk list entry, and
2110Sstevel@tonic-gate  * adds it to the end of a chunk list.
2120Sstevel@tonic-gate  */
2130Sstevel@tonic-gate void
2140Sstevel@tonic-gate clist_add(struct clist **clp, uint32_t xdroff, int len,
2150Sstevel@tonic-gate 	struct mrc *shandle, caddr_t saddr,
2160Sstevel@tonic-gate 	struct mrc *dhandle, caddr_t daddr)
2170Sstevel@tonic-gate {
2180Sstevel@tonic-gate 	struct clist *cl;
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	/* Find the end of the list */
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 	while (*clp != NULL)
2230Sstevel@tonic-gate 		clp = &((*clp)->c_next);
2240Sstevel@tonic-gate 
2257387SRobert.Gordon@Sun.COM 	cl = clist_alloc();
2260Sstevel@tonic-gate 	cl->c_xdroff = xdroff;
2270Sstevel@tonic-gate 	cl->c_len = len;
2287387SRobert.Gordon@Sun.COM 	cl->w.c_saddr = (uint64_t)(uintptr_t)saddr;
2290Sstevel@tonic-gate 	if (shandle)
2300Sstevel@tonic-gate 		cl->c_smemhandle = *shandle;
2317387SRobert.Gordon@Sun.COM 	cl->u.c_daddr = (uint64_t)(uintptr_t)daddr;
2320Sstevel@tonic-gate 	if (dhandle)
2330Sstevel@tonic-gate 		cl->c_dmemhandle = *dhandle;
2340Sstevel@tonic-gate 	cl->c_next = NULL;
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate 	*clp = cl;
2370Sstevel@tonic-gate }
2380Sstevel@tonic-gate 
2397387SRobert.Gordon@Sun.COM rdma_stat
2407387SRobert.Gordon@Sun.COM clist_register(CONN *conn, struct clist *cl, clist_dstsrc dstsrc)
2410Sstevel@tonic-gate {
2420Sstevel@tonic-gate 	struct clist *c;
2430Sstevel@tonic-gate 	int status;
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 	for (c = cl; c; c = c->c_next) {
2467387SRobert.Gordon@Sun.COM 		if (c->c_len <= 0)
2477387SRobert.Gordon@Sun.COM 			continue;
2487387SRobert.Gordon@Sun.COM 		switch (dstsrc) {
2497387SRobert.Gordon@Sun.COM 		case CLIST_REG_SOURCE:
2500Sstevel@tonic-gate 			status = RDMA_REGMEMSYNC(conn,
2517387SRobert.Gordon@Sun.COM 			    (caddr_t)(struct as *)cl->c_adspc,
2527387SRobert.Gordon@Sun.COM 			    (caddr_t)(uintptr_t)c->w.c_saddr3, c->c_len,
2537387SRobert.Gordon@Sun.COM 			    &c->c_smemhandle, (void **)&c->c_ssynchandle,
2547387SRobert.Gordon@Sun.COM 			    (void *)c->rb_longbuf.rb_private);
2557387SRobert.Gordon@Sun.COM 			break;
2567387SRobert.Gordon@Sun.COM 		case CLIST_REG_DST:
2570Sstevel@tonic-gate 			status = RDMA_REGMEMSYNC(conn,
2587387SRobert.Gordon@Sun.COM 			    (caddr_t)(struct as *)cl->c_adspc,
2597387SRobert.Gordon@Sun.COM 			    (caddr_t)(uintptr_t)c->u.c_daddr3, c->c_len,
2607387SRobert.Gordon@Sun.COM 			    &c->c_dmemhandle, (void **)&c->c_dsynchandle,
2617387SRobert.Gordon@Sun.COM 			    (void *)c->rb_longbuf.rb_private);
2627387SRobert.Gordon@Sun.COM 			break;
2637387SRobert.Gordon@Sun.COM 		default:
2647387SRobert.Gordon@Sun.COM 			return (RDMA_INVAL);
2650Sstevel@tonic-gate 		}
2660Sstevel@tonic-gate 		if (status != RDMA_SUCCESS) {
2677387SRobert.Gordon@Sun.COM 			(void) clist_deregister(conn, cl, dstsrc);
2680Sstevel@tonic-gate 			return (status);
2690Sstevel@tonic-gate 		}
2700Sstevel@tonic-gate 	}
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 	return (RDMA_SUCCESS);
2730Sstevel@tonic-gate }
2740Sstevel@tonic-gate 
2757387SRobert.Gordon@Sun.COM rdma_stat
2767387SRobert.Gordon@Sun.COM clist_deregister(CONN *conn, struct clist *cl, clist_dstsrc dstsrc)
2770Sstevel@tonic-gate {
2780Sstevel@tonic-gate 	struct clist *c;
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate 	for (c = cl; c; c = c->c_next) {
2817387SRobert.Gordon@Sun.COM 		switch (dstsrc) {
2827387SRobert.Gordon@Sun.COM 		case CLIST_REG_SOURCE:
2830Sstevel@tonic-gate 			if (c->c_smemhandle.mrc_rmr != 0) {
2840Sstevel@tonic-gate 				(void) RDMA_DEREGMEMSYNC(conn,
2857387SRobert.Gordon@Sun.COM 				    (caddr_t)(uintptr_t)c->w.c_saddr3,
2860Sstevel@tonic-gate 				    c->c_smemhandle,
2877387SRobert.Gordon@Sun.COM 				    (void *)(uintptr_t)c->c_ssynchandle,
2887387SRobert.Gordon@Sun.COM 				    (void *)c->rb_longbuf.rb_private);
2890Sstevel@tonic-gate 				c->c_smemhandle.mrc_rmr = 0;
2900Sstevel@tonic-gate 				c->c_ssynchandle = NULL;
2910Sstevel@tonic-gate 			}
2927387SRobert.Gordon@Sun.COM 			break;
2937387SRobert.Gordon@Sun.COM 		case CLIST_REG_DST:
2940Sstevel@tonic-gate 			if (c->c_dmemhandle.mrc_rmr != 0) {
2950Sstevel@tonic-gate 				(void) RDMA_DEREGMEMSYNC(conn,
2967387SRobert.Gordon@Sun.COM 				    (caddr_t)(uintptr_t)c->u.c_daddr3,
2970Sstevel@tonic-gate 				    c->c_dmemhandle,
2987387SRobert.Gordon@Sun.COM 				    (void *)(uintptr_t)c->c_dsynchandle,
2997387SRobert.Gordon@Sun.COM 				    (void *)c->rb_longbuf.rb_private);
3000Sstevel@tonic-gate 				c->c_dmemhandle.mrc_rmr = 0;
3010Sstevel@tonic-gate 				c->c_dsynchandle = NULL;
3020Sstevel@tonic-gate 			}
3037387SRobert.Gordon@Sun.COM 			break;
3047387SRobert.Gordon@Sun.COM 		default:
3057387SRobert.Gordon@Sun.COM 			return (RDMA_INVAL);
3060Sstevel@tonic-gate 		}
3070Sstevel@tonic-gate 	}
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 	return (RDMA_SUCCESS);
3100Sstevel@tonic-gate }
3110Sstevel@tonic-gate 
3127387SRobert.Gordon@Sun.COM rdma_stat
3137387SRobert.Gordon@Sun.COM clist_syncmem(CONN *conn, struct clist *cl, clist_dstsrc dstsrc)
3147387SRobert.Gordon@Sun.COM {
3157387SRobert.Gordon@Sun.COM 	struct clist *c;
3167387SRobert.Gordon@Sun.COM 	rdma_stat status;
3177387SRobert.Gordon@Sun.COM 
3187387SRobert.Gordon@Sun.COM 	c = cl;
3197387SRobert.Gordon@Sun.COM 	switch (dstsrc) {
3207387SRobert.Gordon@Sun.COM 	case CLIST_REG_SOURCE:
3217387SRobert.Gordon@Sun.COM 		while (c != NULL) {
3227387SRobert.Gordon@Sun.COM 			if (c->c_ssynchandle) {
3237387SRobert.Gordon@Sun.COM 				status = RDMA_SYNCMEM(conn,
3247387SRobert.Gordon@Sun.COM 				    (void *)(uintptr_t)c->c_ssynchandle,
3257387SRobert.Gordon@Sun.COM 				    (caddr_t)(uintptr_t)c->w.c_saddr3,
3267387SRobert.Gordon@Sun.COM 				    c->c_len, 0);
3277387SRobert.Gordon@Sun.COM 				if (status != RDMA_SUCCESS)
3287387SRobert.Gordon@Sun.COM 					return (status);
3297387SRobert.Gordon@Sun.COM 			}
3307387SRobert.Gordon@Sun.COM 			c = c->c_next;
3317387SRobert.Gordon@Sun.COM 		}
3327387SRobert.Gordon@Sun.COM 		break;
3337387SRobert.Gordon@Sun.COM 	case CLIST_REG_DST:
3347387SRobert.Gordon@Sun.COM 		while (c != NULL) {
3357387SRobert.Gordon@Sun.COM 			if (c->c_ssynchandle) {
3367387SRobert.Gordon@Sun.COM 				status = RDMA_SYNCMEM(conn,
3377387SRobert.Gordon@Sun.COM 				    (void *)(uintptr_t)c->c_dsynchandle,
3387387SRobert.Gordon@Sun.COM 				    (caddr_t)(uintptr_t)c->u.c_daddr3,
3397387SRobert.Gordon@Sun.COM 				    c->c_len, 1);
3407387SRobert.Gordon@Sun.COM 				if (status != RDMA_SUCCESS)
3417387SRobert.Gordon@Sun.COM 					return (status);
3427387SRobert.Gordon@Sun.COM 			}
3437387SRobert.Gordon@Sun.COM 			c = c->c_next;
3447387SRobert.Gordon@Sun.COM 		}
3457387SRobert.Gordon@Sun.COM 		break;
3467387SRobert.Gordon@Sun.COM 	default:
3477387SRobert.Gordon@Sun.COM 		return (RDMA_INVAL);
3487387SRobert.Gordon@Sun.COM 	}
3497387SRobert.Gordon@Sun.COM 
3507387SRobert.Gordon@Sun.COM 	return (RDMA_SUCCESS);
3517387SRobert.Gordon@Sun.COM }
3527387SRobert.Gordon@Sun.COM 
3530Sstevel@tonic-gate /*
3540Sstevel@tonic-gate  * Frees up entries in chunk list
3550Sstevel@tonic-gate  */
3560Sstevel@tonic-gate void
3570Sstevel@tonic-gate clist_free(struct clist *cl)
3580Sstevel@tonic-gate {
3590Sstevel@tonic-gate 	struct clist *c = cl;
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 	while (c != NULL) {
3620Sstevel@tonic-gate 		cl = cl->c_next;
3637387SRobert.Gordon@Sun.COM 		kmem_cache_free(clist_cache, c);
3640Sstevel@tonic-gate 		c = cl;
3650Sstevel@tonic-gate 	}
3660Sstevel@tonic-gate }
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate rdma_stat
3690Sstevel@tonic-gate rdma_clnt_postrecv(CONN *conn, uint32_t xid)
3700Sstevel@tonic-gate {
3710Sstevel@tonic-gate 	struct clist *cl = NULL;
3720Sstevel@tonic-gate 	rdma_stat retval;
3737387SRobert.Gordon@Sun.COM 	rdma_buf_t rbuf = {0};
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate 	rbuf.type = RECV_BUFFER;
3760Sstevel@tonic-gate 	if (RDMA_BUF_ALLOC(conn, &rbuf)) {
3777387SRobert.Gordon@Sun.COM 		return (RDMA_NORESOURCE);
3780Sstevel@tonic-gate 	}
3797387SRobert.Gordon@Sun.COM 
3807387SRobert.Gordon@Sun.COM 	clist_add(&cl, 0, rbuf.len, &rbuf.handle, rbuf.addr,
3817387SRobert.Gordon@Sun.COM 	    NULL, NULL);
3827387SRobert.Gordon@Sun.COM 	retval = RDMA_CLNT_RECVBUF(conn, cl, xid);
3837387SRobert.Gordon@Sun.COM 	clist_free(cl);
3847387SRobert.Gordon@Sun.COM 
3850Sstevel@tonic-gate 	return (retval);
3860Sstevel@tonic-gate }
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate rdma_stat
3897387SRobert.Gordon@Sun.COM rdma_clnt_postrecv_remove(CONN *conn, uint32_t xid)
3907387SRobert.Gordon@Sun.COM {
3917387SRobert.Gordon@Sun.COM 	return (RDMA_CLNT_RECVBUF_REMOVE(conn, xid));
3927387SRobert.Gordon@Sun.COM }
3937387SRobert.Gordon@Sun.COM 
3947387SRobert.Gordon@Sun.COM rdma_stat
3950Sstevel@tonic-gate rdma_svc_postrecv(CONN *conn)
3960Sstevel@tonic-gate {
3970Sstevel@tonic-gate 	struct clist *cl = NULL;
3980Sstevel@tonic-gate 	rdma_stat retval;
3997387SRobert.Gordon@Sun.COM 	rdma_buf_t rbuf = {0};
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate 	rbuf.type = RECV_BUFFER;
4020Sstevel@tonic-gate 	if (RDMA_BUF_ALLOC(conn, &rbuf)) {
4030Sstevel@tonic-gate 		retval = RDMA_NORESOURCE;
4040Sstevel@tonic-gate 	} else {
4050Sstevel@tonic-gate 		clist_add(&cl, 0, rbuf.len, &rbuf.handle, rbuf.addr,
4067387SRobert.Gordon@Sun.COM 		    NULL, NULL);
4070Sstevel@tonic-gate 		retval = RDMA_SVC_RECVBUF(conn, cl);
4080Sstevel@tonic-gate 		clist_free(cl);
4090Sstevel@tonic-gate 	}
4100Sstevel@tonic-gate 	return (retval);
4110Sstevel@tonic-gate }
4120Sstevel@tonic-gate 
4130Sstevel@tonic-gate rdma_stat
4147387SRobert.Gordon@Sun.COM rdma_buf_alloc(CONN *conn, rdma_buf_t *rbuf)
4150Sstevel@tonic-gate {
4167387SRobert.Gordon@Sun.COM 	return (RDMA_BUF_ALLOC(conn, rbuf));
4170Sstevel@tonic-gate }
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate void
4200Sstevel@tonic-gate rdma_buf_free(CONN *conn, rdma_buf_t *rbuf)
4210Sstevel@tonic-gate {
4220Sstevel@tonic-gate 	if (!rbuf || rbuf->addr == NULL) {
4230Sstevel@tonic-gate 		return;
4240Sstevel@tonic-gate 	}
4257387SRobert.Gordon@Sun.COM 	RDMA_BUF_FREE(conn, rbuf);
4267387SRobert.Gordon@Sun.COM 	bzero(rbuf, sizeof (rdma_buf_t));
4270Sstevel@tonic-gate }
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate /*
4300Sstevel@tonic-gate  * Caller is holding rdma_modload_lock mutex
4310Sstevel@tonic-gate  */
4320Sstevel@tonic-gate int
4330Sstevel@tonic-gate rdma_modload()
4340Sstevel@tonic-gate {
4350Sstevel@tonic-gate 	int status;
4360Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&rdma_modload_lock));
4370Sstevel@tonic-gate 	/*
4380Sstevel@tonic-gate 	 * Load all available RDMA plugins which right now is only IB plugin.
4390Sstevel@tonic-gate 	 * If no IB hardware is present, then quit right away.
4400Sstevel@tonic-gate 	 * ENODEV -- For no device on the system
4410Sstevel@tonic-gate 	 * EPROTONOSUPPORT -- For module not avilable either due to failure to
4420Sstevel@tonic-gate 	 * load or some other reason.
4430Sstevel@tonic-gate 	 */
4440Sstevel@tonic-gate 	rdma_modloaded = 1;
4450Sstevel@tonic-gate 	if (ibt_hw_is_present() == 0) {
4460Sstevel@tonic-gate 		rdma_dev_available = 0;
4470Sstevel@tonic-gate 		return (ENODEV);
4480Sstevel@tonic-gate 	}
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate 	rdma_dev_available = 1;
4510Sstevel@tonic-gate 	if (rpcmod_li == NULL)
4520Sstevel@tonic-gate 		return (EPROTONOSUPPORT);
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate 	status = ldi_open_by_name("/devices/ib/rpcib@0:rpcib",
4550Sstevel@tonic-gate 	    FREAD | FWRITE, kcred,
4560Sstevel@tonic-gate 	    &rpcib_handle, rpcmod_li);
457*8695SRajkumar.Sivaprakasam@Sun.COM 
4580Sstevel@tonic-gate 	if (status != 0)
4590Sstevel@tonic-gate 		return (EPROTONOSUPPORT);
4600Sstevel@tonic-gate 
4617387SRobert.Gordon@Sun.COM 
462*8695SRajkumar.Sivaprakasam@Sun.COM 	/*
463*8695SRajkumar.Sivaprakasam@Sun.COM 	 * We will need to reload the plugin module after it was unregistered
464*8695SRajkumar.Sivaprakasam@Sun.COM 	 * but the resources below need to allocated only the first time.
465*8695SRajkumar.Sivaprakasam@Sun.COM 	 */
466*8695SRajkumar.Sivaprakasam@Sun.COM 	if (!clist_cache) {
467*8695SRajkumar.Sivaprakasam@Sun.COM 		clist_cache = kmem_cache_create("rdma_clist",
468*8695SRajkumar.Sivaprakasam@Sun.COM 		    sizeof (struct clist), _POINTER_ALIGNMENT, NULL,
469*8695SRajkumar.Sivaprakasam@Sun.COM 		    NULL, NULL, NULL, 0, 0);
470*8695SRajkumar.Sivaprakasam@Sun.COM 		rdma_kstat_init();
471*8695SRajkumar.Sivaprakasam@Sun.COM 	}
472*8695SRajkumar.Sivaprakasam@Sun.COM 
473*8695SRajkumar.Sivaprakasam@Sun.COM 	(void) ldi_close(rpcib_handle, FREAD|FWRITE, kcred);
4747387SRobert.Gordon@Sun.COM 
4750Sstevel@tonic-gate 	return (0);
4760Sstevel@tonic-gate }
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate void
4790Sstevel@tonic-gate rdma_kstat_init(void)
4800Sstevel@tonic-gate {
4810Sstevel@tonic-gate 	kstat_t *ksp;
4820Sstevel@tonic-gate 
4830Sstevel@tonic-gate 	/*
4840Sstevel@tonic-gate 	 * The RDMA framework doesn't know how to deal with Zones, and is
4850Sstevel@tonic-gate 	 * only available in the global zone.
4860Sstevel@tonic-gate 	 */
4870Sstevel@tonic-gate 	ASSERT(INGLOBALZONE(curproc));
4880Sstevel@tonic-gate 	ksp = kstat_create_zone("unix", 0, "rpc_rdma_client", "rpc",
4890Sstevel@tonic-gate 	    KSTAT_TYPE_NAMED, rdmarcstat_ndata,
4900Sstevel@tonic-gate 	    KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE, GLOBAL_ZONEID);
4910Sstevel@tonic-gate 	if (ksp) {
4920Sstevel@tonic-gate 		ksp->ks_data = (void *) rdmarcstat_ptr;
4930Sstevel@tonic-gate 		kstat_install(ksp);
4940Sstevel@tonic-gate 	}
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate 	ksp = kstat_create_zone("unix", 0, "rpc_rdma_server", "rpc",
4970Sstevel@tonic-gate 	    KSTAT_TYPE_NAMED, rdmarsstat_ndata,
4980Sstevel@tonic-gate 	    KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE, GLOBAL_ZONEID);
4990Sstevel@tonic-gate 	if (ksp) {
5000Sstevel@tonic-gate 		ksp->ks_data = (void *) rdmarsstat_ptr;
5010Sstevel@tonic-gate 		kstat_install(ksp);
5020Sstevel@tonic-gate 	}
5030Sstevel@tonic-gate }
504*8695SRajkumar.Sivaprakasam@Sun.COM 
505*8695SRajkumar.Sivaprakasam@Sun.COM rdma_stat
506*8695SRajkumar.Sivaprakasam@Sun.COM rdma_kwait(void)
507*8695SRajkumar.Sivaprakasam@Sun.COM {
508*8695SRajkumar.Sivaprakasam@Sun.COM 	int ret;
509*8695SRajkumar.Sivaprakasam@Sun.COM 	rdma_stat stat;
510*8695SRajkumar.Sivaprakasam@Sun.COM 
511*8695SRajkumar.Sivaprakasam@Sun.COM 	mutex_enter(&rdma_wait.svc_lock);
512*8695SRajkumar.Sivaprakasam@Sun.COM 
513*8695SRajkumar.Sivaprakasam@Sun.COM 	ret = cv_wait_sig(&rdma_wait.svc_cv, &rdma_wait.svc_lock);
514*8695SRajkumar.Sivaprakasam@Sun.COM 
515*8695SRajkumar.Sivaprakasam@Sun.COM 	/*
516*8695SRajkumar.Sivaprakasam@Sun.COM 	 * If signalled by a hca attach/detach, pass the right
517*8695SRajkumar.Sivaprakasam@Sun.COM 	 * stat back.
518*8695SRajkumar.Sivaprakasam@Sun.COM 	 */
519*8695SRajkumar.Sivaprakasam@Sun.COM 
520*8695SRajkumar.Sivaprakasam@Sun.COM 	if (ret)
521*8695SRajkumar.Sivaprakasam@Sun.COM 		stat =  rdma_wait.svc_stat;
522*8695SRajkumar.Sivaprakasam@Sun.COM 	else
523*8695SRajkumar.Sivaprakasam@Sun.COM 		stat = RDMA_INTR;
524*8695SRajkumar.Sivaprakasam@Sun.COM 
525*8695SRajkumar.Sivaprakasam@Sun.COM 	mutex_exit(&rdma_wait.svc_lock);
526*8695SRajkumar.Sivaprakasam@Sun.COM 
527*8695SRajkumar.Sivaprakasam@Sun.COM 	return (stat);
528*8695SRajkumar.Sivaprakasam@Sun.COM }
529