1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <sys/systm.h>
30*0Sstevel@tonic-gate #include <sys/kstat.h>
31*0Sstevel@tonic-gate #include <sys/modctl.h>
32*0Sstevel@tonic-gate #include <rpc/rpc_rdma.h>
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate #include <sys/ib/ibtl/ibti.h>
35*0Sstevel@tonic-gate 
36*0Sstevel@tonic-gate /*
37*0Sstevel@tonic-gate  * RDMA chunk size
38*0Sstevel@tonic-gate  */
39*0Sstevel@tonic-gate #define	RDMA_MINCHUNK	1024
40*0Sstevel@tonic-gate uint_t rdma_minchunk = RDMA_MINCHUNK;
41*0Sstevel@tonic-gate 
42*0Sstevel@tonic-gate /*
43*0Sstevel@tonic-gate  * Globals
44*0Sstevel@tonic-gate  */
45*0Sstevel@tonic-gate int rdma_modloaded = 0;		/* flag to load RDMA plugin modules */
46*0Sstevel@tonic-gate int rdma_dev_available = 0;	/* if any RDMA device is loaded */
47*0Sstevel@tonic-gate kmutex_t rdma_modload_lock;	/* protects rdma_modloaded flag */
48*0Sstevel@tonic-gate rdma_registry_t	*rdma_mod_head = NULL;	/* head for RDMA modules */
49*0Sstevel@tonic-gate krwlock_t	rdma_lock;		/* protects rdma_mod_head list */
50*0Sstevel@tonic-gate ldi_ident_t rpcmod_li = NULL;	/* identifies us with ldi_ framework */
51*0Sstevel@tonic-gate 
52*0Sstevel@tonic-gate /*
53*0Sstevel@tonic-gate  * Statics
54*0Sstevel@tonic-gate  */
55*0Sstevel@tonic-gate static ldi_handle_t rpcib_handle = NULL;
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate /*
58*0Sstevel@tonic-gate  * Externs
59*0Sstevel@tonic-gate  */
60*0Sstevel@tonic-gate extern	kstat_named_t	*rdmarcstat_ptr;
61*0Sstevel@tonic-gate extern	uint_t		rdmarcstat_ndata;
62*0Sstevel@tonic-gate extern	kstat_named_t	*rdmarsstat_ptr;
63*0Sstevel@tonic-gate extern	uint_t		rdmarsstat_ndata;
64*0Sstevel@tonic-gate 
65*0Sstevel@tonic-gate void rdma_kstat_init();
66*0Sstevel@tonic-gate 
67*0Sstevel@tonic-gate /*
68*0Sstevel@tonic-gate  * RDMATF module registration routine.
69*0Sstevel@tonic-gate  * This routine is expected to be called by the init routine in
70*0Sstevel@tonic-gate  * the plugin modules.
71*0Sstevel@tonic-gate  */
72*0Sstevel@tonic-gate rdma_stat
73*0Sstevel@tonic-gate rdma_register_mod(rdma_mod_t *mod)
74*0Sstevel@tonic-gate {
75*0Sstevel@tonic-gate 	rdma_registry_t **mp, *m;
76*0Sstevel@tonic-gate 
77*0Sstevel@tonic-gate 	if (mod->rdma_version != RDMATF_VERS) {
78*0Sstevel@tonic-gate 		return (RDMA_BADVERS);
79*0Sstevel@tonic-gate 	}
80*0Sstevel@tonic-gate 
81*0Sstevel@tonic-gate 	rw_enter(&rdma_lock, RW_WRITER);
82*0Sstevel@tonic-gate 	/*
83*0Sstevel@tonic-gate 	 * Ensure not already registered
84*0Sstevel@tonic-gate 	 */
85*0Sstevel@tonic-gate 	mp = &rdma_mod_head;
86*0Sstevel@tonic-gate 	while (*mp != NULL) {
87*0Sstevel@tonic-gate 		if (strncmp((*mp)->r_mod->rdma_api, mod->rdma_api,
88*0Sstevel@tonic-gate 		    KNC_STRSIZE) == 0) {
89*0Sstevel@tonic-gate 			rw_exit(&rdma_lock);
90*0Sstevel@tonic-gate 			return (RDMA_REG_EXIST);
91*0Sstevel@tonic-gate 		}
92*0Sstevel@tonic-gate 		mp = &((*mp)->r_next);
93*0Sstevel@tonic-gate 	}
94*0Sstevel@tonic-gate 
95*0Sstevel@tonic-gate 	/*
96*0Sstevel@tonic-gate 	 * New one, create and add to registry
97*0Sstevel@tonic-gate 	 */
98*0Sstevel@tonic-gate 	m = kmem_alloc(sizeof (rdma_registry_t), KM_SLEEP);
99*0Sstevel@tonic-gate 	m->r_mod = kmem_alloc(sizeof (rdma_mod_t), KM_SLEEP);
100*0Sstevel@tonic-gate 	*m->r_mod = *mod;
101*0Sstevel@tonic-gate 	m->r_next = NULL;
102*0Sstevel@tonic-gate 	m->r_mod->rdma_api = kmem_zalloc(KNC_STRSIZE, KM_SLEEP);
103*0Sstevel@tonic-gate 	(void) strncpy(m->r_mod->rdma_api, mod->rdma_api, KNC_STRSIZE);
104*0Sstevel@tonic-gate 	m->r_mod->rdma_api[KNC_STRSIZE - 1] = '\0';
105*0Sstevel@tonic-gate 	*mp = m;
106*0Sstevel@tonic-gate 	rw_exit(&rdma_lock);
107*0Sstevel@tonic-gate 
108*0Sstevel@tonic-gate 	return (RDMA_SUCCESS);
109*0Sstevel@tonic-gate }
110*0Sstevel@tonic-gate 
111*0Sstevel@tonic-gate /*
112*0Sstevel@tonic-gate  * RDMATF module unregistration routine.
113*0Sstevel@tonic-gate  * This routine is expected to be called by the fini routine in
114*0Sstevel@tonic-gate  * the plugin modules.
115*0Sstevel@tonic-gate  */
116*0Sstevel@tonic-gate rdma_stat
117*0Sstevel@tonic-gate rdma_unregister_mod(rdma_mod_t *mod)
118*0Sstevel@tonic-gate {
119*0Sstevel@tonic-gate 	rdma_registry_t **m, *mmod = NULL;
120*0Sstevel@tonic-gate 
121*0Sstevel@tonic-gate 	rw_enter(&rdma_lock, RW_WRITER);
122*0Sstevel@tonic-gate 
123*0Sstevel@tonic-gate 	m = &rdma_mod_head;
124*0Sstevel@tonic-gate 	while (*m != NULL) {
125*0Sstevel@tonic-gate 		if (strncmp((*m)->r_mod->rdma_api, mod->rdma_api,
126*0Sstevel@tonic-gate 		    KNC_STRSIZE) != 0) {
127*0Sstevel@tonic-gate 			m = &((*m)->r_next);
128*0Sstevel@tonic-gate 			continue;
129*0Sstevel@tonic-gate 		}
130*0Sstevel@tonic-gate 		/*
131*0Sstevel@tonic-gate 		 * Check if any device attached, if so return error
132*0Sstevel@tonic-gate 		 */
133*0Sstevel@tonic-gate 		if ((*m)->r_mod->rdma_count != 0) {
134*0Sstevel@tonic-gate 			rw_exit(&rdma_lock);
135*0Sstevel@tonic-gate 			return (RDMA_FAILED);
136*0Sstevel@tonic-gate 		}
137*0Sstevel@tonic-gate 		/*
138*0Sstevel@tonic-gate 		 * Found entry. Now remove it.
139*0Sstevel@tonic-gate 		 */
140*0Sstevel@tonic-gate 		mmod = *m;
141*0Sstevel@tonic-gate 		*m = (*m)->r_next;
142*0Sstevel@tonic-gate 		kmem_free(mmod->r_mod->rdma_api, KNC_STRSIZE);
143*0Sstevel@tonic-gate 		kmem_free(mmod->r_mod, sizeof (rdma_mod_t));
144*0Sstevel@tonic-gate 		kmem_free(mmod, sizeof (rdma_registry_t));
145*0Sstevel@tonic-gate 		rw_exit(&rdma_lock);
146*0Sstevel@tonic-gate 		return (RDMA_SUCCESS);
147*0Sstevel@tonic-gate 	}
148*0Sstevel@tonic-gate 
149*0Sstevel@tonic-gate 	/*
150*0Sstevel@tonic-gate 	 * Not found.
151*0Sstevel@tonic-gate 	 */
152*0Sstevel@tonic-gate 	rw_exit(&rdma_lock);
153*0Sstevel@tonic-gate 	return (RDMA_FAILED);
154*0Sstevel@tonic-gate }
155*0Sstevel@tonic-gate 
156*0Sstevel@tonic-gate /*
157*0Sstevel@tonic-gate  * Creates a new chunk list entry, and
158*0Sstevel@tonic-gate  * adds it to the end of a chunk list.
159*0Sstevel@tonic-gate  */
160*0Sstevel@tonic-gate void
161*0Sstevel@tonic-gate clist_add(struct clist **clp, uint32_t xdroff, int len,
162*0Sstevel@tonic-gate 	struct mrc *shandle, caddr_t saddr,
163*0Sstevel@tonic-gate 	struct mrc *dhandle, caddr_t daddr)
164*0Sstevel@tonic-gate {
165*0Sstevel@tonic-gate 	struct clist *cl;
166*0Sstevel@tonic-gate 
167*0Sstevel@tonic-gate 	/* Find the end of the list */
168*0Sstevel@tonic-gate 
169*0Sstevel@tonic-gate 	while (*clp != NULL)
170*0Sstevel@tonic-gate 		clp = &((*clp)->c_next);
171*0Sstevel@tonic-gate 
172*0Sstevel@tonic-gate 	cl = kmem_zalloc(sizeof (*cl), KM_SLEEP);
173*0Sstevel@tonic-gate 	cl->c_xdroff = xdroff;
174*0Sstevel@tonic-gate 	cl->c_len = len;
175*0Sstevel@tonic-gate 	cl->c_saddr = (uint64_t)(uintptr_t)saddr;
176*0Sstevel@tonic-gate 	if (shandle)
177*0Sstevel@tonic-gate 		cl->c_smemhandle = *shandle;
178*0Sstevel@tonic-gate 	cl->c_daddr = (uint64_t)(uintptr_t)daddr;
179*0Sstevel@tonic-gate 	if (dhandle)
180*0Sstevel@tonic-gate 		cl->c_dmemhandle = *dhandle;
181*0Sstevel@tonic-gate 	cl->c_next = NULL;
182*0Sstevel@tonic-gate 
183*0Sstevel@tonic-gate 	*clp = cl;
184*0Sstevel@tonic-gate }
185*0Sstevel@tonic-gate 
186*0Sstevel@tonic-gate int
187*0Sstevel@tonic-gate clist_register(CONN *conn, struct clist *cl, bool_t src)
188*0Sstevel@tonic-gate {
189*0Sstevel@tonic-gate 	struct clist *c;
190*0Sstevel@tonic-gate 	int status;
191*0Sstevel@tonic-gate 
192*0Sstevel@tonic-gate 	for (c = cl; c; c = c->c_next) {
193*0Sstevel@tonic-gate 		if (src) {
194*0Sstevel@tonic-gate 			status = RDMA_REGMEMSYNC(conn,
195*0Sstevel@tonic-gate 			    (caddr_t)(uintptr_t)c->c_saddr, c->c_len,
196*0Sstevel@tonic-gate 			    &c->c_smemhandle, (void **)&c->c_ssynchandle);
197*0Sstevel@tonic-gate 		} else {
198*0Sstevel@tonic-gate 			status = RDMA_REGMEMSYNC(conn,
199*0Sstevel@tonic-gate 			    (caddr_t)(uintptr_t)c->c_daddr, c->c_len,
200*0Sstevel@tonic-gate 			    &c->c_dmemhandle, (void **)&c->c_dsynchandle);
201*0Sstevel@tonic-gate 		}
202*0Sstevel@tonic-gate 		if (status != RDMA_SUCCESS) {
203*0Sstevel@tonic-gate 			(void) clist_deregister(conn, cl, src);
204*0Sstevel@tonic-gate 			return (status);
205*0Sstevel@tonic-gate 		}
206*0Sstevel@tonic-gate 	}
207*0Sstevel@tonic-gate 
208*0Sstevel@tonic-gate 	return (RDMA_SUCCESS);
209*0Sstevel@tonic-gate }
210*0Sstevel@tonic-gate 
211*0Sstevel@tonic-gate int
212*0Sstevel@tonic-gate clist_deregister(CONN *conn, struct clist *cl, bool_t src)
213*0Sstevel@tonic-gate {
214*0Sstevel@tonic-gate 	struct clist *c;
215*0Sstevel@tonic-gate 
216*0Sstevel@tonic-gate 	for (c = cl; c; c = c->c_next) {
217*0Sstevel@tonic-gate 		if (src) {
218*0Sstevel@tonic-gate 			if (c->c_smemhandle.mrc_rmr != 0) {
219*0Sstevel@tonic-gate 				(void) RDMA_DEREGMEMSYNC(conn,
220*0Sstevel@tonic-gate 				    (caddr_t)(uintptr_t)c->c_saddr,
221*0Sstevel@tonic-gate 				    c->c_smemhandle,
222*0Sstevel@tonic-gate 				    (void *)(uintptr_t)c->c_ssynchandle);
223*0Sstevel@tonic-gate 				c->c_smemhandle.mrc_rmr = 0;
224*0Sstevel@tonic-gate 				c->c_ssynchandle = NULL;
225*0Sstevel@tonic-gate 			}
226*0Sstevel@tonic-gate 		} else {
227*0Sstevel@tonic-gate 			if (c->c_dmemhandle.mrc_rmr != 0) {
228*0Sstevel@tonic-gate 				(void) RDMA_DEREGMEMSYNC(conn,
229*0Sstevel@tonic-gate 				    (caddr_t)(uintptr_t)c->c_daddr,
230*0Sstevel@tonic-gate 				    c->c_dmemhandle,
231*0Sstevel@tonic-gate 				    (void *)(uintptr_t)c->c_dsynchandle);
232*0Sstevel@tonic-gate 				c->c_dmemhandle.mrc_rmr = 0;
233*0Sstevel@tonic-gate 				c->c_dsynchandle = NULL;
234*0Sstevel@tonic-gate 			}
235*0Sstevel@tonic-gate 		}
236*0Sstevel@tonic-gate 	}
237*0Sstevel@tonic-gate 
238*0Sstevel@tonic-gate 	return (RDMA_SUCCESS);
239*0Sstevel@tonic-gate }
240*0Sstevel@tonic-gate 
241*0Sstevel@tonic-gate /*
242*0Sstevel@tonic-gate  * Frees up entries in chunk list
243*0Sstevel@tonic-gate  */
244*0Sstevel@tonic-gate void
245*0Sstevel@tonic-gate clist_free(struct clist *cl)
246*0Sstevel@tonic-gate {
247*0Sstevel@tonic-gate 	struct clist *c = cl;
248*0Sstevel@tonic-gate 
249*0Sstevel@tonic-gate 	while (c != NULL) {
250*0Sstevel@tonic-gate 		cl = cl->c_next;
251*0Sstevel@tonic-gate 		kmem_free(c, sizeof (struct clist));
252*0Sstevel@tonic-gate 		c = cl;
253*0Sstevel@tonic-gate 	}
254*0Sstevel@tonic-gate }
255*0Sstevel@tonic-gate 
256*0Sstevel@tonic-gate rdma_stat
257*0Sstevel@tonic-gate rdma_clnt_postrecv(CONN *conn, uint32_t xid)
258*0Sstevel@tonic-gate {
259*0Sstevel@tonic-gate 	struct clist *cl = NULL;
260*0Sstevel@tonic-gate 	rdma_stat retval;
261*0Sstevel@tonic-gate 	rdma_buf_t rbuf;
262*0Sstevel@tonic-gate 
263*0Sstevel@tonic-gate 	rbuf.type = RECV_BUFFER;
264*0Sstevel@tonic-gate 	if (RDMA_BUF_ALLOC(conn, &rbuf)) {
265*0Sstevel@tonic-gate 		retval = RDMA_NORESOURCE;
266*0Sstevel@tonic-gate 	} else {
267*0Sstevel@tonic-gate 		clist_add(&cl, 0, rbuf.len, &rbuf.handle, rbuf.addr,
268*0Sstevel@tonic-gate 			NULL, NULL);
269*0Sstevel@tonic-gate 		retval = RDMA_CLNT_RECVBUF(conn, cl, xid);
270*0Sstevel@tonic-gate 		clist_free(cl);
271*0Sstevel@tonic-gate 	}
272*0Sstevel@tonic-gate 	return (retval);
273*0Sstevel@tonic-gate }
274*0Sstevel@tonic-gate 
275*0Sstevel@tonic-gate rdma_stat
276*0Sstevel@tonic-gate rdma_svc_postrecv(CONN *conn)
277*0Sstevel@tonic-gate {
278*0Sstevel@tonic-gate 	struct clist *cl = NULL;
279*0Sstevel@tonic-gate 	rdma_stat retval;
280*0Sstevel@tonic-gate 	rdma_buf_t rbuf;
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate 	rbuf.type = RECV_BUFFER;
283*0Sstevel@tonic-gate 	if (RDMA_BUF_ALLOC(conn, &rbuf)) {
284*0Sstevel@tonic-gate 		retval = RDMA_NORESOURCE;
285*0Sstevel@tonic-gate 	} else {
286*0Sstevel@tonic-gate 		clist_add(&cl, 0, rbuf.len, &rbuf.handle, rbuf.addr,
287*0Sstevel@tonic-gate 			NULL, NULL);
288*0Sstevel@tonic-gate 		retval = RDMA_SVC_RECVBUF(conn, cl);
289*0Sstevel@tonic-gate 		clist_free(cl);
290*0Sstevel@tonic-gate 	}
291*0Sstevel@tonic-gate 	return (retval);
292*0Sstevel@tonic-gate }
293*0Sstevel@tonic-gate 
294*0Sstevel@tonic-gate rdma_stat
295*0Sstevel@tonic-gate clist_syncmem(CONN *conn, struct clist *cl, bool_t src)
296*0Sstevel@tonic-gate {
297*0Sstevel@tonic-gate 	struct clist *c;
298*0Sstevel@tonic-gate 	rdma_stat status;
299*0Sstevel@tonic-gate 
300*0Sstevel@tonic-gate 	c = cl;
301*0Sstevel@tonic-gate 	if (src) {
302*0Sstevel@tonic-gate 		while (c != NULL) {
303*0Sstevel@tonic-gate 			status = RDMA_SYNCMEM(conn,
304*0Sstevel@tonic-gate 			    (void *)(uintptr_t)c->c_ssynchandle,
305*0Sstevel@tonic-gate 			    (caddr_t)(uintptr_t)c->c_saddr, c->c_len, 0);
306*0Sstevel@tonic-gate 			if (status != RDMA_SUCCESS)
307*0Sstevel@tonic-gate 				return (status);
308*0Sstevel@tonic-gate 			c = c->c_next;
309*0Sstevel@tonic-gate 		}
310*0Sstevel@tonic-gate 	} else {
311*0Sstevel@tonic-gate 		while (c != NULL) {
312*0Sstevel@tonic-gate 			status = RDMA_SYNCMEM(conn,
313*0Sstevel@tonic-gate 			    (void *)(uintptr_t)c->c_dsynchandle,
314*0Sstevel@tonic-gate 			    (caddr_t)(uintptr_t)c->c_daddr, c->c_len, 1);
315*0Sstevel@tonic-gate 			if (status != RDMA_SUCCESS)
316*0Sstevel@tonic-gate 				return (status);
317*0Sstevel@tonic-gate 			c = c->c_next;
318*0Sstevel@tonic-gate 		}
319*0Sstevel@tonic-gate 	}
320*0Sstevel@tonic-gate 	return (RDMA_SUCCESS);
321*0Sstevel@tonic-gate }
322*0Sstevel@tonic-gate 
323*0Sstevel@tonic-gate void
324*0Sstevel@tonic-gate rdma_buf_free(CONN *conn, rdma_buf_t *rbuf)
325*0Sstevel@tonic-gate {
326*0Sstevel@tonic-gate 	if (!rbuf || rbuf->addr == NULL) {
327*0Sstevel@tonic-gate 		return;
328*0Sstevel@tonic-gate 	}
329*0Sstevel@tonic-gate 	if (rbuf->type != CHUNK_BUFFER) {
330*0Sstevel@tonic-gate 		/* pool buffer */
331*0Sstevel@tonic-gate 		RDMA_BUF_FREE(conn, rbuf);
332*0Sstevel@tonic-gate 	} else {
333*0Sstevel@tonic-gate 		kmem_free(rbuf->addr, rbuf->len);
334*0Sstevel@tonic-gate 	}
335*0Sstevel@tonic-gate 	rbuf->addr = NULL;
336*0Sstevel@tonic-gate 	rbuf->len = 0;
337*0Sstevel@tonic-gate }
338*0Sstevel@tonic-gate 
339*0Sstevel@tonic-gate /*
340*0Sstevel@tonic-gate  * Caller is holding rdma_modload_lock mutex
341*0Sstevel@tonic-gate  */
342*0Sstevel@tonic-gate int
343*0Sstevel@tonic-gate rdma_modload()
344*0Sstevel@tonic-gate {
345*0Sstevel@tonic-gate 	int status;
346*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&rdma_modload_lock));
347*0Sstevel@tonic-gate 	/*
348*0Sstevel@tonic-gate 	 * Load all available RDMA plugins which right now is only IB plugin.
349*0Sstevel@tonic-gate 	 * If no IB hardware is present, then quit right away.
350*0Sstevel@tonic-gate 	 * ENODEV -- For no device on the system
351*0Sstevel@tonic-gate 	 * EPROTONOSUPPORT -- For module not avilable either due to failure to
352*0Sstevel@tonic-gate 	 * load or some other reason.
353*0Sstevel@tonic-gate 	 */
354*0Sstevel@tonic-gate 	rdma_modloaded = 1;
355*0Sstevel@tonic-gate 	if (ibt_hw_is_present() == 0) {
356*0Sstevel@tonic-gate 		rdma_dev_available = 0;
357*0Sstevel@tonic-gate 		return (ENODEV);
358*0Sstevel@tonic-gate 	}
359*0Sstevel@tonic-gate 
360*0Sstevel@tonic-gate 	rdma_dev_available = 1;
361*0Sstevel@tonic-gate 	if (rpcmod_li == NULL)
362*0Sstevel@tonic-gate 		return (EPROTONOSUPPORT);
363*0Sstevel@tonic-gate 
364*0Sstevel@tonic-gate 	status = ldi_open_by_name("/devices/ib/rpcib@0:rpcib",
365*0Sstevel@tonic-gate 	    FREAD | FWRITE, kcred,
366*0Sstevel@tonic-gate 	    &rpcib_handle, rpcmod_li);
367*0Sstevel@tonic-gate 	if (status != 0)
368*0Sstevel@tonic-gate 		return (EPROTONOSUPPORT);
369*0Sstevel@tonic-gate 
370*0Sstevel@tonic-gate 	/* success */
371*0Sstevel@tonic-gate 	rdma_kstat_init();
372*0Sstevel@tonic-gate 	return (0);
373*0Sstevel@tonic-gate }
374*0Sstevel@tonic-gate 
375*0Sstevel@tonic-gate void
376*0Sstevel@tonic-gate rdma_kstat_init(void)
377*0Sstevel@tonic-gate {
378*0Sstevel@tonic-gate 	kstat_t *ksp;
379*0Sstevel@tonic-gate 
380*0Sstevel@tonic-gate 	/*
381*0Sstevel@tonic-gate 	 * The RDMA framework doesn't know how to deal with Zones, and is
382*0Sstevel@tonic-gate 	 * only available in the global zone.
383*0Sstevel@tonic-gate 	 */
384*0Sstevel@tonic-gate 	ASSERT(INGLOBALZONE(curproc));
385*0Sstevel@tonic-gate 	ksp = kstat_create_zone("unix", 0, "rpc_rdma_client", "rpc",
386*0Sstevel@tonic-gate 	    KSTAT_TYPE_NAMED, rdmarcstat_ndata,
387*0Sstevel@tonic-gate 	    KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE, GLOBAL_ZONEID);
388*0Sstevel@tonic-gate 	if (ksp) {
389*0Sstevel@tonic-gate 		ksp->ks_data = (void *) rdmarcstat_ptr;
390*0Sstevel@tonic-gate 		kstat_install(ksp);
391*0Sstevel@tonic-gate 	}
392*0Sstevel@tonic-gate 
393*0Sstevel@tonic-gate 	ksp = kstat_create_zone("unix", 0, "rpc_rdma_server", "rpc",
394*0Sstevel@tonic-gate 	    KSTAT_TYPE_NAMED, rdmarsstat_ndata,
395*0Sstevel@tonic-gate 	    KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE, GLOBAL_ZONEID);
396*0Sstevel@tonic-gate 	if (ksp) {
397*0Sstevel@tonic-gate 		ksp->ks_data = (void *) rdmarsstat_ptr;
398*0Sstevel@tonic-gate 		kstat_install(ksp);
399*0Sstevel@tonic-gate 	}
400*0Sstevel@tonic-gate }
401