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
5*7387SRobert.Gordon@Sun.COM  * Common Development and Distribution License (the "License").
6*7387SRobert.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*7387SRobert.Gordon@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
26*7387SRobert.Gordon@Sun.COM /*
27*7387SRobert.Gordon@Sun.COM  * Copyright (c) 2007, The Ohio State University. All rights reserved.
28*7387SRobert.Gordon@Sun.COM  *
29*7387SRobert.Gordon@Sun.COM  * Portions of this source code is developed by the team members of
30*7387SRobert.Gordon@Sun.COM  * The Ohio State University's Network-Based Computing Laboratory (NBCL),
31*7387SRobert.Gordon@Sun.COM  * headed by Professor Dhabaleswar K. (DK) Panda.
32*7387SRobert.Gordon@Sun.COM  *
33*7387SRobert.Gordon@Sun.COM  * Acknowledgements to contributions from developors:
34*7387SRobert.Gordon@Sun.COM  *   Ranjit Noronha: noronha@cse.ohio-state.edu
35*7387SRobert.Gordon@Sun.COM  *   Lei Chai      : chail@cse.ohio-state.edu
36*7387SRobert.Gordon@Sun.COM  *   Weikuan Yu    : yuw@cse.ohio-state.edu
37*7387SRobert.Gordon@Sun.COM  *
38*7387SRobert.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>
43*7387SRobert.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 */
560Sstevel@tonic-gate rdma_registry_t	*rdma_mod_head = NULL;	/* head for RDMA modules */
570Sstevel@tonic-gate krwlock_t	rdma_lock;		/* protects rdma_mod_head list */
580Sstevel@tonic-gate ldi_ident_t rpcmod_li = NULL;	/* identifies us with ldi_ framework */
590Sstevel@tonic-gate 
60*7387SRobert.Gordon@Sun.COM kmem_cache_t *clist_cache = NULL;
61*7387SRobert.Gordon@Sun.COM 
620Sstevel@tonic-gate /*
630Sstevel@tonic-gate  * Statics
640Sstevel@tonic-gate  */
650Sstevel@tonic-gate static ldi_handle_t rpcib_handle = NULL;
660Sstevel@tonic-gate 
670Sstevel@tonic-gate /*
680Sstevel@tonic-gate  * Externs
690Sstevel@tonic-gate  */
700Sstevel@tonic-gate extern	kstat_named_t	*rdmarcstat_ptr;
710Sstevel@tonic-gate extern	uint_t		rdmarcstat_ndata;
720Sstevel@tonic-gate extern	kstat_named_t	*rdmarsstat_ptr;
730Sstevel@tonic-gate extern	uint_t		rdmarsstat_ndata;
740Sstevel@tonic-gate 
750Sstevel@tonic-gate void rdma_kstat_init();
760Sstevel@tonic-gate 
770Sstevel@tonic-gate /*
780Sstevel@tonic-gate  * RDMATF module registration routine.
790Sstevel@tonic-gate  * This routine is expected to be called by the init routine in
800Sstevel@tonic-gate  * the plugin modules.
810Sstevel@tonic-gate  */
820Sstevel@tonic-gate rdma_stat
830Sstevel@tonic-gate rdma_register_mod(rdma_mod_t *mod)
840Sstevel@tonic-gate {
850Sstevel@tonic-gate 	rdma_registry_t **mp, *m;
860Sstevel@tonic-gate 
870Sstevel@tonic-gate 	if (mod->rdma_version != RDMATF_VERS) {
880Sstevel@tonic-gate 		return (RDMA_BADVERS);
890Sstevel@tonic-gate 	}
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	rw_enter(&rdma_lock, RW_WRITER);
920Sstevel@tonic-gate 	/*
930Sstevel@tonic-gate 	 * Ensure not already registered
940Sstevel@tonic-gate 	 */
950Sstevel@tonic-gate 	mp = &rdma_mod_head;
960Sstevel@tonic-gate 	while (*mp != NULL) {
970Sstevel@tonic-gate 		if (strncmp((*mp)->r_mod->rdma_api, mod->rdma_api,
980Sstevel@tonic-gate 		    KNC_STRSIZE) == 0) {
990Sstevel@tonic-gate 			rw_exit(&rdma_lock);
1000Sstevel@tonic-gate 			return (RDMA_REG_EXIST);
1010Sstevel@tonic-gate 		}
1020Sstevel@tonic-gate 		mp = &((*mp)->r_next);
1030Sstevel@tonic-gate 	}
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate 	/*
1060Sstevel@tonic-gate 	 * New one, create and add to registry
1070Sstevel@tonic-gate 	 */
1080Sstevel@tonic-gate 	m = kmem_alloc(sizeof (rdma_registry_t), KM_SLEEP);
1090Sstevel@tonic-gate 	m->r_mod = kmem_alloc(sizeof (rdma_mod_t), KM_SLEEP);
1100Sstevel@tonic-gate 	*m->r_mod = *mod;
1110Sstevel@tonic-gate 	m->r_next = NULL;
1120Sstevel@tonic-gate 	m->r_mod->rdma_api = kmem_zalloc(KNC_STRSIZE, KM_SLEEP);
1130Sstevel@tonic-gate 	(void) strncpy(m->r_mod->rdma_api, mod->rdma_api, KNC_STRSIZE);
1140Sstevel@tonic-gate 	m->r_mod->rdma_api[KNC_STRSIZE - 1] = '\0';
1150Sstevel@tonic-gate 	*mp = m;
1160Sstevel@tonic-gate 	rw_exit(&rdma_lock);
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate 	return (RDMA_SUCCESS);
1190Sstevel@tonic-gate }
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate /*
1220Sstevel@tonic-gate  * RDMATF module unregistration routine.
1230Sstevel@tonic-gate  * This routine is expected to be called by the fini routine in
1240Sstevel@tonic-gate  * the plugin modules.
1250Sstevel@tonic-gate  */
1260Sstevel@tonic-gate rdma_stat
1270Sstevel@tonic-gate rdma_unregister_mod(rdma_mod_t *mod)
1280Sstevel@tonic-gate {
1290Sstevel@tonic-gate 	rdma_registry_t **m, *mmod = NULL;
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate 	rw_enter(&rdma_lock, RW_WRITER);
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate 	m = &rdma_mod_head;
1340Sstevel@tonic-gate 	while (*m != NULL) {
1350Sstevel@tonic-gate 		if (strncmp((*m)->r_mod->rdma_api, mod->rdma_api,
1360Sstevel@tonic-gate 		    KNC_STRSIZE) != 0) {
1370Sstevel@tonic-gate 			m = &((*m)->r_next);
1380Sstevel@tonic-gate 			continue;
1390Sstevel@tonic-gate 		}
1400Sstevel@tonic-gate 		/*
1410Sstevel@tonic-gate 		 * Check if any device attached, if so return error
1420Sstevel@tonic-gate 		 */
1430Sstevel@tonic-gate 		if ((*m)->r_mod->rdma_count != 0) {
1440Sstevel@tonic-gate 			rw_exit(&rdma_lock);
1450Sstevel@tonic-gate 			return (RDMA_FAILED);
1460Sstevel@tonic-gate 		}
1470Sstevel@tonic-gate 		/*
1480Sstevel@tonic-gate 		 * Found entry. Now remove it.
1490Sstevel@tonic-gate 		 */
1500Sstevel@tonic-gate 		mmod = *m;
1510Sstevel@tonic-gate 		*m = (*m)->r_next;
1520Sstevel@tonic-gate 		kmem_free(mmod->r_mod->rdma_api, KNC_STRSIZE);
1530Sstevel@tonic-gate 		kmem_free(mmod->r_mod, sizeof (rdma_mod_t));
1540Sstevel@tonic-gate 		kmem_free(mmod, sizeof (rdma_registry_t));
1550Sstevel@tonic-gate 		rw_exit(&rdma_lock);
1560Sstevel@tonic-gate 		return (RDMA_SUCCESS);
1570Sstevel@tonic-gate 	}
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 	/*
1600Sstevel@tonic-gate 	 * Not found.
1610Sstevel@tonic-gate 	 */
1620Sstevel@tonic-gate 	rw_exit(&rdma_lock);
1630Sstevel@tonic-gate 	return (RDMA_FAILED);
1640Sstevel@tonic-gate }
1650Sstevel@tonic-gate 
166*7387SRobert.Gordon@Sun.COM struct clist *
167*7387SRobert.Gordon@Sun.COM clist_alloc(void)
168*7387SRobert.Gordon@Sun.COM {
169*7387SRobert.Gordon@Sun.COM 	struct clist *clp;
170*7387SRobert.Gordon@Sun.COM 
171*7387SRobert.Gordon@Sun.COM 	clp = kmem_cache_alloc(clist_cache, KM_SLEEP);
172*7387SRobert.Gordon@Sun.COM 
173*7387SRobert.Gordon@Sun.COM 	bzero(clp, sizeof (*clp));
174*7387SRobert.Gordon@Sun.COM 
175*7387SRobert.Gordon@Sun.COM 	return (clp);
176*7387SRobert.Gordon@Sun.COM }
177*7387SRobert.Gordon@Sun.COM 
1780Sstevel@tonic-gate /*
1790Sstevel@tonic-gate  * Creates a new chunk list entry, and
1800Sstevel@tonic-gate  * adds it to the end of a chunk list.
1810Sstevel@tonic-gate  */
1820Sstevel@tonic-gate void
1830Sstevel@tonic-gate clist_add(struct clist **clp, uint32_t xdroff, int len,
1840Sstevel@tonic-gate 	struct mrc *shandle, caddr_t saddr,
1850Sstevel@tonic-gate 	struct mrc *dhandle, caddr_t daddr)
1860Sstevel@tonic-gate {
1870Sstevel@tonic-gate 	struct clist *cl;
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate 	/* Find the end of the list */
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate 	while (*clp != NULL)
1920Sstevel@tonic-gate 		clp = &((*clp)->c_next);
1930Sstevel@tonic-gate 
194*7387SRobert.Gordon@Sun.COM 	cl = clist_alloc();
1950Sstevel@tonic-gate 	cl->c_xdroff = xdroff;
1960Sstevel@tonic-gate 	cl->c_len = len;
197*7387SRobert.Gordon@Sun.COM 	cl->w.c_saddr = (uint64_t)(uintptr_t)saddr;
1980Sstevel@tonic-gate 	if (shandle)
1990Sstevel@tonic-gate 		cl->c_smemhandle = *shandle;
200*7387SRobert.Gordon@Sun.COM 	cl->u.c_daddr = (uint64_t)(uintptr_t)daddr;
2010Sstevel@tonic-gate 	if (dhandle)
2020Sstevel@tonic-gate 		cl->c_dmemhandle = *dhandle;
2030Sstevel@tonic-gate 	cl->c_next = NULL;
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 	*clp = cl;
2060Sstevel@tonic-gate }
2070Sstevel@tonic-gate 
208*7387SRobert.Gordon@Sun.COM rdma_stat
209*7387SRobert.Gordon@Sun.COM clist_register(CONN *conn, struct clist *cl, clist_dstsrc dstsrc)
2100Sstevel@tonic-gate {
2110Sstevel@tonic-gate 	struct clist *c;
2120Sstevel@tonic-gate 	int status;
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate 	for (c = cl; c; c = c->c_next) {
215*7387SRobert.Gordon@Sun.COM 		if (c->c_len <= 0)
216*7387SRobert.Gordon@Sun.COM 			continue;
217*7387SRobert.Gordon@Sun.COM 		switch (dstsrc) {
218*7387SRobert.Gordon@Sun.COM 		case CLIST_REG_SOURCE:
2190Sstevel@tonic-gate 			status = RDMA_REGMEMSYNC(conn,
220*7387SRobert.Gordon@Sun.COM 			    (caddr_t)(struct as *)cl->c_adspc,
221*7387SRobert.Gordon@Sun.COM 			    (caddr_t)(uintptr_t)c->w.c_saddr3, c->c_len,
222*7387SRobert.Gordon@Sun.COM 			    &c->c_smemhandle, (void **)&c->c_ssynchandle,
223*7387SRobert.Gordon@Sun.COM 			    (void *)c->rb_longbuf.rb_private);
224*7387SRobert.Gordon@Sun.COM 			break;
225*7387SRobert.Gordon@Sun.COM 		case CLIST_REG_DST:
2260Sstevel@tonic-gate 			status = RDMA_REGMEMSYNC(conn,
227*7387SRobert.Gordon@Sun.COM 			    (caddr_t)(struct as *)cl->c_adspc,
228*7387SRobert.Gordon@Sun.COM 			    (caddr_t)(uintptr_t)c->u.c_daddr3, c->c_len,
229*7387SRobert.Gordon@Sun.COM 			    &c->c_dmemhandle, (void **)&c->c_dsynchandle,
230*7387SRobert.Gordon@Sun.COM 			    (void *)c->rb_longbuf.rb_private);
231*7387SRobert.Gordon@Sun.COM 			break;
232*7387SRobert.Gordon@Sun.COM 		default:
233*7387SRobert.Gordon@Sun.COM 			return (RDMA_INVAL);
2340Sstevel@tonic-gate 		}
2350Sstevel@tonic-gate 		if (status != RDMA_SUCCESS) {
236*7387SRobert.Gordon@Sun.COM 			(void) clist_deregister(conn, cl, dstsrc);
2370Sstevel@tonic-gate 			return (status);
2380Sstevel@tonic-gate 		}
2390Sstevel@tonic-gate 	}
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate 	return (RDMA_SUCCESS);
2420Sstevel@tonic-gate }
2430Sstevel@tonic-gate 
244*7387SRobert.Gordon@Sun.COM rdma_stat
245*7387SRobert.Gordon@Sun.COM clist_deregister(CONN *conn, struct clist *cl, clist_dstsrc dstsrc)
2460Sstevel@tonic-gate {
2470Sstevel@tonic-gate 	struct clist *c;
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 	for (c = cl; c; c = c->c_next) {
250*7387SRobert.Gordon@Sun.COM 		switch (dstsrc) {
251*7387SRobert.Gordon@Sun.COM 		case CLIST_REG_SOURCE:
2520Sstevel@tonic-gate 			if (c->c_smemhandle.mrc_rmr != 0) {
2530Sstevel@tonic-gate 				(void) RDMA_DEREGMEMSYNC(conn,
254*7387SRobert.Gordon@Sun.COM 				    (caddr_t)(uintptr_t)c->w.c_saddr3,
2550Sstevel@tonic-gate 				    c->c_smemhandle,
256*7387SRobert.Gordon@Sun.COM 				    (void *)(uintptr_t)c->c_ssynchandle,
257*7387SRobert.Gordon@Sun.COM 				    (void *)c->rb_longbuf.rb_private);
2580Sstevel@tonic-gate 				c->c_smemhandle.mrc_rmr = 0;
2590Sstevel@tonic-gate 				c->c_ssynchandle = NULL;
2600Sstevel@tonic-gate 			}
261*7387SRobert.Gordon@Sun.COM 			break;
262*7387SRobert.Gordon@Sun.COM 		case CLIST_REG_DST:
2630Sstevel@tonic-gate 			if (c->c_dmemhandle.mrc_rmr != 0) {
2640Sstevel@tonic-gate 				(void) RDMA_DEREGMEMSYNC(conn,
265*7387SRobert.Gordon@Sun.COM 				    (caddr_t)(uintptr_t)c->u.c_daddr3,
2660Sstevel@tonic-gate 				    c->c_dmemhandle,
267*7387SRobert.Gordon@Sun.COM 				    (void *)(uintptr_t)c->c_dsynchandle,
268*7387SRobert.Gordon@Sun.COM 				    (void *)c->rb_longbuf.rb_private);
2690Sstevel@tonic-gate 				c->c_dmemhandle.mrc_rmr = 0;
2700Sstevel@tonic-gate 				c->c_dsynchandle = NULL;
2710Sstevel@tonic-gate 			}
272*7387SRobert.Gordon@Sun.COM 			break;
273*7387SRobert.Gordon@Sun.COM 		default:
274*7387SRobert.Gordon@Sun.COM 			return (RDMA_INVAL);
2750Sstevel@tonic-gate 		}
2760Sstevel@tonic-gate 	}
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 	return (RDMA_SUCCESS);
2790Sstevel@tonic-gate }
2800Sstevel@tonic-gate 
281*7387SRobert.Gordon@Sun.COM rdma_stat
282*7387SRobert.Gordon@Sun.COM clist_syncmem(CONN *conn, struct clist *cl, clist_dstsrc dstsrc)
283*7387SRobert.Gordon@Sun.COM {
284*7387SRobert.Gordon@Sun.COM 	struct clist *c;
285*7387SRobert.Gordon@Sun.COM 	rdma_stat status;
286*7387SRobert.Gordon@Sun.COM 
287*7387SRobert.Gordon@Sun.COM 	c = cl;
288*7387SRobert.Gordon@Sun.COM 	switch (dstsrc) {
289*7387SRobert.Gordon@Sun.COM 	case CLIST_REG_SOURCE:
290*7387SRobert.Gordon@Sun.COM 		while (c != NULL) {
291*7387SRobert.Gordon@Sun.COM 			if (c->c_ssynchandle) {
292*7387SRobert.Gordon@Sun.COM 				status = RDMA_SYNCMEM(conn,
293*7387SRobert.Gordon@Sun.COM 				    (void *)(uintptr_t)c->c_ssynchandle,
294*7387SRobert.Gordon@Sun.COM 				    (caddr_t)(uintptr_t)c->w.c_saddr3,
295*7387SRobert.Gordon@Sun.COM 				    c->c_len, 0);
296*7387SRobert.Gordon@Sun.COM 				if (status != RDMA_SUCCESS)
297*7387SRobert.Gordon@Sun.COM 					return (status);
298*7387SRobert.Gordon@Sun.COM 			}
299*7387SRobert.Gordon@Sun.COM 			c = c->c_next;
300*7387SRobert.Gordon@Sun.COM 		}
301*7387SRobert.Gordon@Sun.COM 		break;
302*7387SRobert.Gordon@Sun.COM 	case CLIST_REG_DST:
303*7387SRobert.Gordon@Sun.COM 		while (c != NULL) {
304*7387SRobert.Gordon@Sun.COM 			if (c->c_ssynchandle) {
305*7387SRobert.Gordon@Sun.COM 				status = RDMA_SYNCMEM(conn,
306*7387SRobert.Gordon@Sun.COM 				    (void *)(uintptr_t)c->c_dsynchandle,
307*7387SRobert.Gordon@Sun.COM 				    (caddr_t)(uintptr_t)c->u.c_daddr3,
308*7387SRobert.Gordon@Sun.COM 				    c->c_len, 1);
309*7387SRobert.Gordon@Sun.COM 				if (status != RDMA_SUCCESS)
310*7387SRobert.Gordon@Sun.COM 					return (status);
311*7387SRobert.Gordon@Sun.COM 			}
312*7387SRobert.Gordon@Sun.COM 			c = c->c_next;
313*7387SRobert.Gordon@Sun.COM 		}
314*7387SRobert.Gordon@Sun.COM 		break;
315*7387SRobert.Gordon@Sun.COM 	default:
316*7387SRobert.Gordon@Sun.COM 		return (RDMA_INVAL);
317*7387SRobert.Gordon@Sun.COM 	}
318*7387SRobert.Gordon@Sun.COM 
319*7387SRobert.Gordon@Sun.COM 	return (RDMA_SUCCESS);
320*7387SRobert.Gordon@Sun.COM }
321*7387SRobert.Gordon@Sun.COM 
3220Sstevel@tonic-gate /*
3230Sstevel@tonic-gate  * Frees up entries in chunk list
3240Sstevel@tonic-gate  */
3250Sstevel@tonic-gate void
3260Sstevel@tonic-gate clist_free(struct clist *cl)
3270Sstevel@tonic-gate {
3280Sstevel@tonic-gate 	struct clist *c = cl;
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 	while (c != NULL) {
3310Sstevel@tonic-gate 		cl = cl->c_next;
332*7387SRobert.Gordon@Sun.COM 		kmem_cache_free(clist_cache, c);
3330Sstevel@tonic-gate 		c = cl;
3340Sstevel@tonic-gate 	}
3350Sstevel@tonic-gate }
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate rdma_stat
3380Sstevel@tonic-gate rdma_clnt_postrecv(CONN *conn, uint32_t xid)
3390Sstevel@tonic-gate {
3400Sstevel@tonic-gate 	struct clist *cl = NULL;
3410Sstevel@tonic-gate 	rdma_stat retval;
342*7387SRobert.Gordon@Sun.COM 	rdma_buf_t rbuf = {0};
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate 	rbuf.type = RECV_BUFFER;
3450Sstevel@tonic-gate 	if (RDMA_BUF_ALLOC(conn, &rbuf)) {
346*7387SRobert.Gordon@Sun.COM 		return (RDMA_NORESOURCE);
3470Sstevel@tonic-gate 	}
348*7387SRobert.Gordon@Sun.COM 
349*7387SRobert.Gordon@Sun.COM 	clist_add(&cl, 0, rbuf.len, &rbuf.handle, rbuf.addr,
350*7387SRobert.Gordon@Sun.COM 	    NULL, NULL);
351*7387SRobert.Gordon@Sun.COM 	retval = RDMA_CLNT_RECVBUF(conn, cl, xid);
352*7387SRobert.Gordon@Sun.COM 	clist_free(cl);
353*7387SRobert.Gordon@Sun.COM 
3540Sstevel@tonic-gate 	return (retval);
3550Sstevel@tonic-gate }
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate rdma_stat
358*7387SRobert.Gordon@Sun.COM rdma_clnt_postrecv_remove(CONN *conn, uint32_t xid)
359*7387SRobert.Gordon@Sun.COM {
360*7387SRobert.Gordon@Sun.COM 	return (RDMA_CLNT_RECVBUF_REMOVE(conn, xid));
361*7387SRobert.Gordon@Sun.COM }
362*7387SRobert.Gordon@Sun.COM 
363*7387SRobert.Gordon@Sun.COM rdma_stat
3640Sstevel@tonic-gate rdma_svc_postrecv(CONN *conn)
3650Sstevel@tonic-gate {
3660Sstevel@tonic-gate 	struct clist *cl = NULL;
3670Sstevel@tonic-gate 	rdma_stat retval;
368*7387SRobert.Gordon@Sun.COM 	rdma_buf_t rbuf = {0};
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate 	rbuf.type = RECV_BUFFER;
3710Sstevel@tonic-gate 	if (RDMA_BUF_ALLOC(conn, &rbuf)) {
3720Sstevel@tonic-gate 		retval = RDMA_NORESOURCE;
3730Sstevel@tonic-gate 	} else {
3740Sstevel@tonic-gate 		clist_add(&cl, 0, rbuf.len, &rbuf.handle, rbuf.addr,
375*7387SRobert.Gordon@Sun.COM 		    NULL, NULL);
3760Sstevel@tonic-gate 		retval = RDMA_SVC_RECVBUF(conn, cl);
3770Sstevel@tonic-gate 		clist_free(cl);
3780Sstevel@tonic-gate 	}
3790Sstevel@tonic-gate 	return (retval);
3800Sstevel@tonic-gate }
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate rdma_stat
383*7387SRobert.Gordon@Sun.COM rdma_buf_alloc(CONN *conn, rdma_buf_t *rbuf)
3840Sstevel@tonic-gate {
385*7387SRobert.Gordon@Sun.COM 	return (RDMA_BUF_ALLOC(conn, rbuf));
3860Sstevel@tonic-gate }
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate void
3890Sstevel@tonic-gate rdma_buf_free(CONN *conn, rdma_buf_t *rbuf)
3900Sstevel@tonic-gate {
3910Sstevel@tonic-gate 	if (!rbuf || rbuf->addr == NULL) {
3920Sstevel@tonic-gate 		return;
3930Sstevel@tonic-gate 	}
394*7387SRobert.Gordon@Sun.COM 	RDMA_BUF_FREE(conn, rbuf);
395*7387SRobert.Gordon@Sun.COM 	bzero(rbuf, sizeof (rdma_buf_t));
3960Sstevel@tonic-gate }
3970Sstevel@tonic-gate 
3980Sstevel@tonic-gate /*
3990Sstevel@tonic-gate  * Caller is holding rdma_modload_lock mutex
4000Sstevel@tonic-gate  */
4010Sstevel@tonic-gate int
4020Sstevel@tonic-gate rdma_modload()
4030Sstevel@tonic-gate {
4040Sstevel@tonic-gate 	int status;
4050Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&rdma_modload_lock));
4060Sstevel@tonic-gate 	/*
4070Sstevel@tonic-gate 	 * Load all available RDMA plugins which right now is only IB plugin.
4080Sstevel@tonic-gate 	 * If no IB hardware is present, then quit right away.
4090Sstevel@tonic-gate 	 * ENODEV -- For no device on the system
4100Sstevel@tonic-gate 	 * EPROTONOSUPPORT -- For module not avilable either due to failure to
4110Sstevel@tonic-gate 	 * load or some other reason.
4120Sstevel@tonic-gate 	 */
4130Sstevel@tonic-gate 	rdma_modloaded = 1;
4140Sstevel@tonic-gate 	if (ibt_hw_is_present() == 0) {
4150Sstevel@tonic-gate 		rdma_dev_available = 0;
4160Sstevel@tonic-gate 		return (ENODEV);
4170Sstevel@tonic-gate 	}
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 	rdma_dev_available = 1;
4200Sstevel@tonic-gate 	if (rpcmod_li == NULL)
4210Sstevel@tonic-gate 		return (EPROTONOSUPPORT);
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 	status = ldi_open_by_name("/devices/ib/rpcib@0:rpcib",
4240Sstevel@tonic-gate 	    FREAD | FWRITE, kcred,
4250Sstevel@tonic-gate 	    &rpcib_handle, rpcmod_li);
4260Sstevel@tonic-gate 	if (status != 0)
4270Sstevel@tonic-gate 		return (EPROTONOSUPPORT);
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate 	/* success */
4300Sstevel@tonic-gate 	rdma_kstat_init();
431*7387SRobert.Gordon@Sun.COM 
432*7387SRobert.Gordon@Sun.COM 	clist_cache = kmem_cache_create("rdma_clist",
433*7387SRobert.Gordon@Sun.COM 	    sizeof (struct clist), _POINTER_ALIGNMENT, NULL,
434*7387SRobert.Gordon@Sun.COM 	    NULL, NULL, NULL, 0, 0);
435*7387SRobert.Gordon@Sun.COM 
4360Sstevel@tonic-gate 	return (0);
4370Sstevel@tonic-gate }
4380Sstevel@tonic-gate 
4390Sstevel@tonic-gate void
4400Sstevel@tonic-gate rdma_kstat_init(void)
4410Sstevel@tonic-gate {
4420Sstevel@tonic-gate 	kstat_t *ksp;
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate 	/*
4450Sstevel@tonic-gate 	 * The RDMA framework doesn't know how to deal with Zones, and is
4460Sstevel@tonic-gate 	 * only available in the global zone.
4470Sstevel@tonic-gate 	 */
4480Sstevel@tonic-gate 	ASSERT(INGLOBALZONE(curproc));
4490Sstevel@tonic-gate 	ksp = kstat_create_zone("unix", 0, "rpc_rdma_client", "rpc",
4500Sstevel@tonic-gate 	    KSTAT_TYPE_NAMED, rdmarcstat_ndata,
4510Sstevel@tonic-gate 	    KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE, GLOBAL_ZONEID);
4520Sstevel@tonic-gate 	if (ksp) {
4530Sstevel@tonic-gate 		ksp->ks_data = (void *) rdmarcstat_ptr;
4540Sstevel@tonic-gate 		kstat_install(ksp);
4550Sstevel@tonic-gate 	}
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate 	ksp = kstat_create_zone("unix", 0, "rpc_rdma_server", "rpc",
4580Sstevel@tonic-gate 	    KSTAT_TYPE_NAMED, rdmarsstat_ndata,
4590Sstevel@tonic-gate 	    KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE, GLOBAL_ZONEID);
4600Sstevel@tonic-gate 	if (ksp) {
4610Sstevel@tonic-gate 		ksp->ks_data = (void *) rdmarsstat_ptr;
4620Sstevel@tonic-gate 		kstat_install(ksp);
4630Sstevel@tonic-gate 	}
4640Sstevel@tonic-gate }
465