xref: /onnv-gate/usr/src/uts/common/rpc/rdma_subr.c (revision 9348:7155ecb17858)
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 /*
228695SRajkumar.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 /*
278695SRajkumar.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 */
568695SRajkumar.Sivaprakasam@Sun.COM 
578695SRajkumar.Sivaprakasam@Sun.COM rdma_svc_wait_t rdma_wait;
588695SRajkumar.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  */
688695SRajkumar.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
rdma_register_mod(rdma_mod_t * mod)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) {
1028695SRajkumar.Sivaprakasam@Sun.COM 			if ((*mp)->r_mod_state == RDMA_MOD_INACTIVE) {
1038695SRajkumar.Sivaprakasam@Sun.COM 				(*mp)->r_mod_state = RDMA_MOD_ACTIVE;
1048695SRajkumar.Sivaprakasam@Sun.COM 				(*mp)->r_mod->rdma_ops = mod->rdma_ops;
1058695SRajkumar.Sivaprakasam@Sun.COM 				(*mp)->r_mod->rdma_count = mod->rdma_count;
1068695SRajkumar.Sivaprakasam@Sun.COM 				goto announce_hca;
1078695SRajkumar.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';
1248695SRajkumar.Sivaprakasam@Sun.COM 	m->r_mod_state = RDMA_MOD_ACTIVE;
1250Sstevel@tonic-gate 	*mp = m;
1268695SRajkumar.Sivaprakasam@Sun.COM 
1278695SRajkumar.Sivaprakasam@Sun.COM announce_hca:
1280Sstevel@tonic-gate 	rw_exit(&rdma_lock);
1298695SRajkumar.Sivaprakasam@Sun.COM 	/*
1308695SRajkumar.Sivaprakasam@Sun.COM 	 * Start the nfs service on the rdma xprts.
1318695SRajkumar.Sivaprakasam@Sun.COM 	 * (this notification mechanism will need to change when we support
1328695SRajkumar.Sivaprakasam@Sun.COM 	 * multiple hcas and have support for multiple rdma plugins).
1338695SRajkumar.Sivaprakasam@Sun.COM 	 */
1348695SRajkumar.Sivaprakasam@Sun.COM 	mutex_enter(&rdma_wait.svc_lock);
1358695SRajkumar.Sivaprakasam@Sun.COM 	rdma_wait.svc_stat = RDMA_HCA_ATTACH;
1368695SRajkumar.Sivaprakasam@Sun.COM 	cv_signal(&rdma_wait.svc_cv);
1378695SRajkumar.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
rdma_unregister_mod(rdma_mod_t * mod)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 		 */
1648695SRajkumar.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 		/*
1698695SRajkumar.Sivaprakasam@Sun.COM 		 * Found entry. Mark it inactive.
1700Sstevel@tonic-gate 		 */
1710Sstevel@tonic-gate 		mmod = *m;
1728695SRajkumar.Sivaprakasam@Sun.COM 		mmod->r_mod->rdma_count = 0;
1738695SRajkumar.Sivaprakasam@Sun.COM 		mmod->r_mod_state = RDMA_MOD_INACTIVE;
1748695SRajkumar.Sivaprakasam@Sun.COM 		break;
1750Sstevel@tonic-gate 	}
1760Sstevel@tonic-gate 
1778695SRajkumar.Sivaprakasam@Sun.COM 	rdma_modloaded = 0;
1788695SRajkumar.Sivaprakasam@Sun.COM 	rdma_dev_available = 0;
1798695SRajkumar.Sivaprakasam@Sun.COM 	rw_exit(&rdma_lock);
1808695SRajkumar.Sivaprakasam@Sun.COM 
1818695SRajkumar.Sivaprakasam@Sun.COM 	/*
1828695SRajkumar.Sivaprakasam@Sun.COM 	 * Stop the nfs service running on the rdma xprts.
1838695SRajkumar.Sivaprakasam@Sun.COM 	 * (this notification mechanism will need to change when we support
1848695SRajkumar.Sivaprakasam@Sun.COM 	 * multiple hcas and have support for multiple rdma plugins).
1858695SRajkumar.Sivaprakasam@Sun.COM 	 */
1868695SRajkumar.Sivaprakasam@Sun.COM 	mutex_enter(&rdma_wait.svc_lock);
1878695SRajkumar.Sivaprakasam@Sun.COM 	rdma_wait.svc_stat = RDMA_HCA_DETACH;
1888695SRajkumar.Sivaprakasam@Sun.COM 	cv_signal(&rdma_wait.svc_cv);
1898695SRajkumar.Sivaprakasam@Sun.COM 	mutex_exit(&rdma_wait.svc_lock);
1908695SRajkumar.Sivaprakasam@Sun.COM 
1910Sstevel@tonic-gate 	/*
1920Sstevel@tonic-gate 	 * Not found.
1930Sstevel@tonic-gate 	 */
1948695SRajkumar.Sivaprakasam@Sun.COM 	return (RDMA_SUCCESS);
1950Sstevel@tonic-gate }
1960Sstevel@tonic-gate 
1977387SRobert.Gordon@Sun.COM struct clist *
clist_alloc(void)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 
209*9348SSiddheshwar.Mahesh@Sun.COM uint32_t
clist_len(struct clist * cl)210*9348SSiddheshwar.Mahesh@Sun.COM clist_len(struct clist *cl)
211*9348SSiddheshwar.Mahesh@Sun.COM {
212*9348SSiddheshwar.Mahesh@Sun.COM 	uint32_t len = 0;
213*9348SSiddheshwar.Mahesh@Sun.COM 	while (cl) {
214*9348SSiddheshwar.Mahesh@Sun.COM 		len += cl->c_len;
215*9348SSiddheshwar.Mahesh@Sun.COM 		cl = cl->c_next;
216*9348SSiddheshwar.Mahesh@Sun.COM 	}
217*9348SSiddheshwar.Mahesh@Sun.COM 	return (len);
218*9348SSiddheshwar.Mahesh@Sun.COM }
219*9348SSiddheshwar.Mahesh@Sun.COM 
220*9348SSiddheshwar.Mahesh@Sun.COM void
clist_zero_len(struct clist * cl)221*9348SSiddheshwar.Mahesh@Sun.COM clist_zero_len(struct clist *cl)
222*9348SSiddheshwar.Mahesh@Sun.COM {
223*9348SSiddheshwar.Mahesh@Sun.COM 	while (cl != NULL) {
224*9348SSiddheshwar.Mahesh@Sun.COM 		if (cl->c_dmemhandle.mrc_rmr == 0)
225*9348SSiddheshwar.Mahesh@Sun.COM 			break;
226*9348SSiddheshwar.Mahesh@Sun.COM 		cl->c_len = 0;
227*9348SSiddheshwar.Mahesh@Sun.COM 		cl = cl->c_next;
228*9348SSiddheshwar.Mahesh@Sun.COM 	}
229*9348SSiddheshwar.Mahesh@Sun.COM }
230*9348SSiddheshwar.Mahesh@Sun.COM 
2310Sstevel@tonic-gate /*
2320Sstevel@tonic-gate  * Creates a new chunk list entry, and
2330Sstevel@tonic-gate  * adds it to the end of a chunk list.
2340Sstevel@tonic-gate  */
2350Sstevel@tonic-gate void
clist_add(struct clist ** clp,uint32_t xdroff,int len,struct mrc * shandle,caddr_t saddr,struct mrc * dhandle,caddr_t daddr)2360Sstevel@tonic-gate clist_add(struct clist **clp, uint32_t xdroff, int len,
2370Sstevel@tonic-gate 	struct mrc *shandle, caddr_t saddr,
2380Sstevel@tonic-gate 	struct mrc *dhandle, caddr_t daddr)
2390Sstevel@tonic-gate {
2400Sstevel@tonic-gate 	struct clist *cl;
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 	/* Find the end of the list */
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 	while (*clp != NULL)
2450Sstevel@tonic-gate 		clp = &((*clp)->c_next);
2460Sstevel@tonic-gate 
2477387SRobert.Gordon@Sun.COM 	cl = clist_alloc();
2480Sstevel@tonic-gate 	cl->c_xdroff = xdroff;
2490Sstevel@tonic-gate 	cl->c_len = len;
2507387SRobert.Gordon@Sun.COM 	cl->w.c_saddr = (uint64_t)(uintptr_t)saddr;
2510Sstevel@tonic-gate 	if (shandle)
2520Sstevel@tonic-gate 		cl->c_smemhandle = *shandle;
2537387SRobert.Gordon@Sun.COM 	cl->u.c_daddr = (uint64_t)(uintptr_t)daddr;
2540Sstevel@tonic-gate 	if (dhandle)
2550Sstevel@tonic-gate 		cl->c_dmemhandle = *dhandle;
2560Sstevel@tonic-gate 	cl->c_next = NULL;
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 	*clp = cl;
2590Sstevel@tonic-gate }
2600Sstevel@tonic-gate 
2617387SRobert.Gordon@Sun.COM rdma_stat
clist_register(CONN * conn,struct clist * cl,clist_dstsrc dstsrc)2627387SRobert.Gordon@Sun.COM clist_register(CONN *conn, struct clist *cl, clist_dstsrc dstsrc)
2630Sstevel@tonic-gate {
2640Sstevel@tonic-gate 	struct clist *c;
2650Sstevel@tonic-gate 	int status;
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate 	for (c = cl; c; c = c->c_next) {
2687387SRobert.Gordon@Sun.COM 		if (c->c_len <= 0)
2697387SRobert.Gordon@Sun.COM 			continue;
270*9348SSiddheshwar.Mahesh@Sun.COM 
271*9348SSiddheshwar.Mahesh@Sun.COM 		c->c_regtype = dstsrc;
272*9348SSiddheshwar.Mahesh@Sun.COM 
2737387SRobert.Gordon@Sun.COM 		switch (dstsrc) {
2747387SRobert.Gordon@Sun.COM 		case CLIST_REG_SOURCE:
2750Sstevel@tonic-gate 			status = RDMA_REGMEMSYNC(conn,
276*9348SSiddheshwar.Mahesh@Sun.COM 			    (caddr_t)(struct as *)c->c_adspc,
2777387SRobert.Gordon@Sun.COM 			    (caddr_t)(uintptr_t)c->w.c_saddr3, c->c_len,
2787387SRobert.Gordon@Sun.COM 			    &c->c_smemhandle, (void **)&c->c_ssynchandle,
2797387SRobert.Gordon@Sun.COM 			    (void *)c->rb_longbuf.rb_private);
2807387SRobert.Gordon@Sun.COM 			break;
2817387SRobert.Gordon@Sun.COM 		case CLIST_REG_DST:
2820Sstevel@tonic-gate 			status = RDMA_REGMEMSYNC(conn,
283*9348SSiddheshwar.Mahesh@Sun.COM 			    (caddr_t)(struct as *)c->c_adspc,
2847387SRobert.Gordon@Sun.COM 			    (caddr_t)(uintptr_t)c->u.c_daddr3, c->c_len,
2857387SRobert.Gordon@Sun.COM 			    &c->c_dmemhandle, (void **)&c->c_dsynchandle,
2867387SRobert.Gordon@Sun.COM 			    (void *)c->rb_longbuf.rb_private);
2877387SRobert.Gordon@Sun.COM 			break;
2887387SRobert.Gordon@Sun.COM 		default:
2897387SRobert.Gordon@Sun.COM 			return (RDMA_INVAL);
2900Sstevel@tonic-gate 		}
2910Sstevel@tonic-gate 		if (status != RDMA_SUCCESS) {
292*9348SSiddheshwar.Mahesh@Sun.COM 			(void) clist_deregister(conn, cl);
2930Sstevel@tonic-gate 			return (status);
2940Sstevel@tonic-gate 		}
2950Sstevel@tonic-gate 	}
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate 	return (RDMA_SUCCESS);
2980Sstevel@tonic-gate }
2990Sstevel@tonic-gate 
3007387SRobert.Gordon@Sun.COM rdma_stat
clist_deregister(CONN * conn,struct clist * cl)301*9348SSiddheshwar.Mahesh@Sun.COM clist_deregister(CONN *conn, struct clist *cl)
3020Sstevel@tonic-gate {
3030Sstevel@tonic-gate 	struct clist *c;
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate 	for (c = cl; c; c = c->c_next) {
306*9348SSiddheshwar.Mahesh@Sun.COM 		switch (c->c_regtype) {
3077387SRobert.Gordon@Sun.COM 		case CLIST_REG_SOURCE:
3080Sstevel@tonic-gate 			if (c->c_smemhandle.mrc_rmr != 0) {
3090Sstevel@tonic-gate 				(void) RDMA_DEREGMEMSYNC(conn,
3107387SRobert.Gordon@Sun.COM 				    (caddr_t)(uintptr_t)c->w.c_saddr3,
3110Sstevel@tonic-gate 				    c->c_smemhandle,
3127387SRobert.Gordon@Sun.COM 				    (void *)(uintptr_t)c->c_ssynchandle,
3137387SRobert.Gordon@Sun.COM 				    (void *)c->rb_longbuf.rb_private);
3140Sstevel@tonic-gate 				c->c_smemhandle.mrc_rmr = 0;
3150Sstevel@tonic-gate 				c->c_ssynchandle = NULL;
3160Sstevel@tonic-gate 			}
3177387SRobert.Gordon@Sun.COM 			break;
3187387SRobert.Gordon@Sun.COM 		case CLIST_REG_DST:
3190Sstevel@tonic-gate 			if (c->c_dmemhandle.mrc_rmr != 0) {
3200Sstevel@tonic-gate 				(void) RDMA_DEREGMEMSYNC(conn,
3217387SRobert.Gordon@Sun.COM 				    (caddr_t)(uintptr_t)c->u.c_daddr3,
3220Sstevel@tonic-gate 				    c->c_dmemhandle,
3237387SRobert.Gordon@Sun.COM 				    (void *)(uintptr_t)c->c_dsynchandle,
3247387SRobert.Gordon@Sun.COM 				    (void *)c->rb_longbuf.rb_private);
3250Sstevel@tonic-gate 				c->c_dmemhandle.mrc_rmr = 0;
3260Sstevel@tonic-gate 				c->c_dsynchandle = NULL;
3270Sstevel@tonic-gate 			}
3287387SRobert.Gordon@Sun.COM 			break;
3297387SRobert.Gordon@Sun.COM 		default:
330*9348SSiddheshwar.Mahesh@Sun.COM 			/* clist unregistered. continue */
331*9348SSiddheshwar.Mahesh@Sun.COM 			break;
3320Sstevel@tonic-gate 		}
3330Sstevel@tonic-gate 	}
3340Sstevel@tonic-gate 
3350Sstevel@tonic-gate 	return (RDMA_SUCCESS);
3360Sstevel@tonic-gate }
3370Sstevel@tonic-gate 
3387387SRobert.Gordon@Sun.COM rdma_stat
clist_syncmem(CONN * conn,struct clist * cl,clist_dstsrc dstsrc)3397387SRobert.Gordon@Sun.COM clist_syncmem(CONN *conn, struct clist *cl, clist_dstsrc dstsrc)
3407387SRobert.Gordon@Sun.COM {
3417387SRobert.Gordon@Sun.COM 	struct clist *c;
3427387SRobert.Gordon@Sun.COM 	rdma_stat status;
3437387SRobert.Gordon@Sun.COM 
3447387SRobert.Gordon@Sun.COM 	c = cl;
3457387SRobert.Gordon@Sun.COM 	switch (dstsrc) {
3467387SRobert.Gordon@Sun.COM 	case CLIST_REG_SOURCE:
3477387SRobert.Gordon@Sun.COM 		while (c != NULL) {
3487387SRobert.Gordon@Sun.COM 			if (c->c_ssynchandle) {
3497387SRobert.Gordon@Sun.COM 				status = RDMA_SYNCMEM(conn,
3507387SRobert.Gordon@Sun.COM 				    (void *)(uintptr_t)c->c_ssynchandle,
3517387SRobert.Gordon@Sun.COM 				    (caddr_t)(uintptr_t)c->w.c_saddr3,
3527387SRobert.Gordon@Sun.COM 				    c->c_len, 0);
3537387SRobert.Gordon@Sun.COM 				if (status != RDMA_SUCCESS)
3547387SRobert.Gordon@Sun.COM 					return (status);
3557387SRobert.Gordon@Sun.COM 			}
3567387SRobert.Gordon@Sun.COM 			c = c->c_next;
3577387SRobert.Gordon@Sun.COM 		}
3587387SRobert.Gordon@Sun.COM 		break;
3597387SRobert.Gordon@Sun.COM 	case CLIST_REG_DST:
3607387SRobert.Gordon@Sun.COM 		while (c != NULL) {
3617387SRobert.Gordon@Sun.COM 			if (c->c_ssynchandle) {
3627387SRobert.Gordon@Sun.COM 				status = RDMA_SYNCMEM(conn,
3637387SRobert.Gordon@Sun.COM 				    (void *)(uintptr_t)c->c_dsynchandle,
3647387SRobert.Gordon@Sun.COM 				    (caddr_t)(uintptr_t)c->u.c_daddr3,
3657387SRobert.Gordon@Sun.COM 				    c->c_len, 1);
3667387SRobert.Gordon@Sun.COM 				if (status != RDMA_SUCCESS)
3677387SRobert.Gordon@Sun.COM 					return (status);
3687387SRobert.Gordon@Sun.COM 			}
3697387SRobert.Gordon@Sun.COM 			c = c->c_next;
3707387SRobert.Gordon@Sun.COM 		}
3717387SRobert.Gordon@Sun.COM 		break;
3727387SRobert.Gordon@Sun.COM 	default:
3737387SRobert.Gordon@Sun.COM 		return (RDMA_INVAL);
3747387SRobert.Gordon@Sun.COM 	}
3757387SRobert.Gordon@Sun.COM 
3767387SRobert.Gordon@Sun.COM 	return (RDMA_SUCCESS);
3777387SRobert.Gordon@Sun.COM }
3787387SRobert.Gordon@Sun.COM 
3790Sstevel@tonic-gate /*
3800Sstevel@tonic-gate  * Frees up entries in chunk list
3810Sstevel@tonic-gate  */
3820Sstevel@tonic-gate void
clist_free(struct clist * cl)3830Sstevel@tonic-gate clist_free(struct clist *cl)
3840Sstevel@tonic-gate {
3850Sstevel@tonic-gate 	struct clist *c = cl;
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate 	while (c != NULL) {
3880Sstevel@tonic-gate 		cl = cl->c_next;
3897387SRobert.Gordon@Sun.COM 		kmem_cache_free(clist_cache, c);
3900Sstevel@tonic-gate 		c = cl;
3910Sstevel@tonic-gate 	}
3920Sstevel@tonic-gate }
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate rdma_stat
rdma_clnt_postrecv(CONN * conn,uint32_t xid)3950Sstevel@tonic-gate rdma_clnt_postrecv(CONN *conn, uint32_t xid)
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)) {
4037387SRobert.Gordon@Sun.COM 		return (RDMA_NORESOURCE);
4040Sstevel@tonic-gate 	}
4057387SRobert.Gordon@Sun.COM 
4067387SRobert.Gordon@Sun.COM 	clist_add(&cl, 0, rbuf.len, &rbuf.handle, rbuf.addr,
4077387SRobert.Gordon@Sun.COM 	    NULL, NULL);
4087387SRobert.Gordon@Sun.COM 	retval = RDMA_CLNT_RECVBUF(conn, cl, xid);
4097387SRobert.Gordon@Sun.COM 	clist_free(cl);
4107387SRobert.Gordon@Sun.COM 
4110Sstevel@tonic-gate 	return (retval);
4120Sstevel@tonic-gate }
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate rdma_stat
rdma_clnt_postrecv_remove(CONN * conn,uint32_t xid)4157387SRobert.Gordon@Sun.COM rdma_clnt_postrecv_remove(CONN *conn, uint32_t xid)
4167387SRobert.Gordon@Sun.COM {
4177387SRobert.Gordon@Sun.COM 	return (RDMA_CLNT_RECVBUF_REMOVE(conn, xid));
4187387SRobert.Gordon@Sun.COM }
4197387SRobert.Gordon@Sun.COM 
4207387SRobert.Gordon@Sun.COM rdma_stat
rdma_svc_postrecv(CONN * conn)4210Sstevel@tonic-gate rdma_svc_postrecv(CONN *conn)
4220Sstevel@tonic-gate {
4230Sstevel@tonic-gate 	struct clist *cl = NULL;
4240Sstevel@tonic-gate 	rdma_stat retval;
4257387SRobert.Gordon@Sun.COM 	rdma_buf_t rbuf = {0};
4260Sstevel@tonic-gate 
4270Sstevel@tonic-gate 	rbuf.type = RECV_BUFFER;
4280Sstevel@tonic-gate 	if (RDMA_BUF_ALLOC(conn, &rbuf)) {
4290Sstevel@tonic-gate 		retval = RDMA_NORESOURCE;
4300Sstevel@tonic-gate 	} else {
4310Sstevel@tonic-gate 		clist_add(&cl, 0, rbuf.len, &rbuf.handle, rbuf.addr,
4327387SRobert.Gordon@Sun.COM 		    NULL, NULL);
4330Sstevel@tonic-gate 		retval = RDMA_SVC_RECVBUF(conn, cl);
4340Sstevel@tonic-gate 		clist_free(cl);
4350Sstevel@tonic-gate 	}
4360Sstevel@tonic-gate 	return (retval);
4370Sstevel@tonic-gate }
4380Sstevel@tonic-gate 
4390Sstevel@tonic-gate rdma_stat
rdma_buf_alloc(CONN * conn,rdma_buf_t * rbuf)4407387SRobert.Gordon@Sun.COM rdma_buf_alloc(CONN *conn, rdma_buf_t *rbuf)
4410Sstevel@tonic-gate {
4427387SRobert.Gordon@Sun.COM 	return (RDMA_BUF_ALLOC(conn, rbuf));
4430Sstevel@tonic-gate }
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate void
rdma_buf_free(CONN * conn,rdma_buf_t * rbuf)4460Sstevel@tonic-gate rdma_buf_free(CONN *conn, rdma_buf_t *rbuf)
4470Sstevel@tonic-gate {
4480Sstevel@tonic-gate 	if (!rbuf || rbuf->addr == NULL) {
4490Sstevel@tonic-gate 		return;
4500Sstevel@tonic-gate 	}
4517387SRobert.Gordon@Sun.COM 	RDMA_BUF_FREE(conn, rbuf);
4527387SRobert.Gordon@Sun.COM 	bzero(rbuf, sizeof (rdma_buf_t));
4530Sstevel@tonic-gate }
4540Sstevel@tonic-gate 
4550Sstevel@tonic-gate /*
4560Sstevel@tonic-gate  * Caller is holding rdma_modload_lock mutex
4570Sstevel@tonic-gate  */
4580Sstevel@tonic-gate int
rdma_modload()4590Sstevel@tonic-gate rdma_modload()
4600Sstevel@tonic-gate {
4610Sstevel@tonic-gate 	int status;
4620Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&rdma_modload_lock));
4630Sstevel@tonic-gate 	/*
4640Sstevel@tonic-gate 	 * Load all available RDMA plugins which right now is only IB plugin.
4650Sstevel@tonic-gate 	 * If no IB hardware is present, then quit right away.
4660Sstevel@tonic-gate 	 * ENODEV -- For no device on the system
4670Sstevel@tonic-gate 	 * EPROTONOSUPPORT -- For module not avilable either due to failure to
4680Sstevel@tonic-gate 	 * load or some other reason.
4690Sstevel@tonic-gate 	 */
4700Sstevel@tonic-gate 	rdma_modloaded = 1;
4710Sstevel@tonic-gate 	if (ibt_hw_is_present() == 0) {
4720Sstevel@tonic-gate 		rdma_dev_available = 0;
4730Sstevel@tonic-gate 		return (ENODEV);
4740Sstevel@tonic-gate 	}
4750Sstevel@tonic-gate 
4760Sstevel@tonic-gate 	rdma_dev_available = 1;
4770Sstevel@tonic-gate 	if (rpcmod_li == NULL)
4780Sstevel@tonic-gate 		return (EPROTONOSUPPORT);
4790Sstevel@tonic-gate 
4800Sstevel@tonic-gate 	status = ldi_open_by_name("/devices/ib/rpcib@0:rpcib",
4810Sstevel@tonic-gate 	    FREAD | FWRITE, kcred,
4820Sstevel@tonic-gate 	    &rpcib_handle, rpcmod_li);
4838695SRajkumar.Sivaprakasam@Sun.COM 
4840Sstevel@tonic-gate 	if (status != 0)
4850Sstevel@tonic-gate 		return (EPROTONOSUPPORT);
4860Sstevel@tonic-gate 
4877387SRobert.Gordon@Sun.COM 
4888695SRajkumar.Sivaprakasam@Sun.COM 	/*
4898695SRajkumar.Sivaprakasam@Sun.COM 	 * We will need to reload the plugin module after it was unregistered
4908695SRajkumar.Sivaprakasam@Sun.COM 	 * but the resources below need to allocated only the first time.
4918695SRajkumar.Sivaprakasam@Sun.COM 	 */
4928695SRajkumar.Sivaprakasam@Sun.COM 	if (!clist_cache) {
4938695SRajkumar.Sivaprakasam@Sun.COM 		clist_cache = kmem_cache_create("rdma_clist",
4948695SRajkumar.Sivaprakasam@Sun.COM 		    sizeof (struct clist), _POINTER_ALIGNMENT, NULL,
4958695SRajkumar.Sivaprakasam@Sun.COM 		    NULL, NULL, NULL, 0, 0);
4968695SRajkumar.Sivaprakasam@Sun.COM 		rdma_kstat_init();
4978695SRajkumar.Sivaprakasam@Sun.COM 	}
4988695SRajkumar.Sivaprakasam@Sun.COM 
4998695SRajkumar.Sivaprakasam@Sun.COM 	(void) ldi_close(rpcib_handle, FREAD|FWRITE, kcred);
5007387SRobert.Gordon@Sun.COM 
5010Sstevel@tonic-gate 	return (0);
5020Sstevel@tonic-gate }
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate void
rdma_kstat_init(void)5050Sstevel@tonic-gate rdma_kstat_init(void)
5060Sstevel@tonic-gate {
5070Sstevel@tonic-gate 	kstat_t *ksp;
5080Sstevel@tonic-gate 
5090Sstevel@tonic-gate 	/*
5100Sstevel@tonic-gate 	 * The RDMA framework doesn't know how to deal with Zones, and is
5110Sstevel@tonic-gate 	 * only available in the global zone.
5120Sstevel@tonic-gate 	 */
5130Sstevel@tonic-gate 	ASSERT(INGLOBALZONE(curproc));
5140Sstevel@tonic-gate 	ksp = kstat_create_zone("unix", 0, "rpc_rdma_client", "rpc",
5150Sstevel@tonic-gate 	    KSTAT_TYPE_NAMED, rdmarcstat_ndata,
5160Sstevel@tonic-gate 	    KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE, GLOBAL_ZONEID);
5170Sstevel@tonic-gate 	if (ksp) {
5180Sstevel@tonic-gate 		ksp->ks_data = (void *) rdmarcstat_ptr;
5190Sstevel@tonic-gate 		kstat_install(ksp);
5200Sstevel@tonic-gate 	}
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate 	ksp = kstat_create_zone("unix", 0, "rpc_rdma_server", "rpc",
5230Sstevel@tonic-gate 	    KSTAT_TYPE_NAMED, rdmarsstat_ndata,
5240Sstevel@tonic-gate 	    KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE, GLOBAL_ZONEID);
5250Sstevel@tonic-gate 	if (ksp) {
5260Sstevel@tonic-gate 		ksp->ks_data = (void *) rdmarsstat_ptr;
5270Sstevel@tonic-gate 		kstat_install(ksp);
5280Sstevel@tonic-gate 	}
5290Sstevel@tonic-gate }
5308695SRajkumar.Sivaprakasam@Sun.COM 
5318695SRajkumar.Sivaprakasam@Sun.COM rdma_stat
rdma_kwait(void)5328695SRajkumar.Sivaprakasam@Sun.COM rdma_kwait(void)
5338695SRajkumar.Sivaprakasam@Sun.COM {
5348695SRajkumar.Sivaprakasam@Sun.COM 	int ret;
5358695SRajkumar.Sivaprakasam@Sun.COM 	rdma_stat stat;
5368695SRajkumar.Sivaprakasam@Sun.COM 
5378695SRajkumar.Sivaprakasam@Sun.COM 	mutex_enter(&rdma_wait.svc_lock);
5388695SRajkumar.Sivaprakasam@Sun.COM 
5398695SRajkumar.Sivaprakasam@Sun.COM 	ret = cv_wait_sig(&rdma_wait.svc_cv, &rdma_wait.svc_lock);
5408695SRajkumar.Sivaprakasam@Sun.COM 
5418695SRajkumar.Sivaprakasam@Sun.COM 	/*
5428695SRajkumar.Sivaprakasam@Sun.COM 	 * If signalled by a hca attach/detach, pass the right
5438695SRajkumar.Sivaprakasam@Sun.COM 	 * stat back.
5448695SRajkumar.Sivaprakasam@Sun.COM 	 */
5458695SRajkumar.Sivaprakasam@Sun.COM 
5468695SRajkumar.Sivaprakasam@Sun.COM 	if (ret)
5478695SRajkumar.Sivaprakasam@Sun.COM 		stat =  rdma_wait.svc_stat;
5488695SRajkumar.Sivaprakasam@Sun.COM 	else
5498695SRajkumar.Sivaprakasam@Sun.COM 		stat = RDMA_INTR;
5508695SRajkumar.Sivaprakasam@Sun.COM 
5518695SRajkumar.Sivaprakasam@Sun.COM 	mutex_exit(&rdma_wait.svc_lock);
5528695SRajkumar.Sivaprakasam@Sun.COM 
5538695SRajkumar.Sivaprakasam@Sun.COM 	return (stat);
5548695SRajkumar.Sivaprakasam@Sun.COM }
555