xref: /illumos-gate/usr/src/uts/common/rpc/rpc_rdma.h (revision 129b3e6c5b0ac55b5021a4c38db6387b6acdaaf1)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * Copyright (c) 2007, The Ohio State University. All rights reserved.
28  *
29  * Portions of this source code is developed by the team members of
30  * The Ohio State University's Network-Based Computing Laboratory (NBCL),
31  * headed by Professor Dhabaleswar K. (DK) Panda.
32  *
33  * Acknowledgements to contributions from developors:
34  *   Ranjit Noronha: noronha@cse.ohio-state.edu
35  *   Lei Chai      : chail@cse.ohio-state.edu
36  *   Weikuan Yu    : yuw@cse.ohio-state.edu
37  *
38  */
39 
40 #ifndef	_RPC_RPC_RDMA_H
41 #define	_RPC_RPC_RDMA_H
42 
43 #include <rpc/rpc.h>
44 #include <rpc/rpc_sztypes.h>
45 #include <sys/sunddi.h>
46 #include <sys/sunldi.h>
47 
48 #ifdef __cplusplus
49 extern "C" {
50 #endif
51 
52 #define	RPCRDMA_VERS	1	/* Version of the RPC over RDMA protocol */
53 #define	RDMATF_VERS	1	/* Version of the API used by RPC for RDMA */
54 #define	RDMATF_VERS_1	1	/* Current version of RDMATF */
55 
56 /*
57  * The size of an RPC call or reply message
58  */
59 #define	RPC_MSG_SZ	1024
60 
61 /*
62  * RDMA chunk size
63  */
64 #define	RDMA_MINCHUNK	1024
65 
66 /*
67  * Storage for a chunk list
68  */
69 #define	RPC_CL_SZ  1024
70 
71 /*
72  * Chunk size
73  */
74 #define	MINCHUNK  1024
75 
76 /*
77  * Size of receive buffer
78  */
79 #define	RPC_BUF_SIZE	2048
80 
81 #define	NOWAIT	0	/* don't wait for operation of complete */
82 #define	WAIT	1	/* wait and ensure that operation is complete */
83 
84 /*
85  * RDMA xdr buffer control and other control flags. Add new flags here,
86  * set them in private structure for xdr over RDMA in xdr_rdma.c
87  */
88 #define	XDR_RDMA_CHUNK			0x1
89 #define	XDR_RDMA_WLIST_REG		0x2
90 #define	XDR_RDMA_RLIST_REG		0x4
91 
92 #define	LONG_REPLY_LEN	65536
93 #define	WCL_BUF_LEN	32768
94 #define	RCL_BUF_LEN	32768
95 
96 
97 #define	RDMA_BUFS_RQST	34	/* Num bufs requested by client */
98 #define	RDMA_BUFS_GRANT	32	/* Num bufs granted by server */
99 
100 struct xdr_ops *xdrrdma_xops(void);
101 
102 /*
103  * Credit Control Structures.
104  */
105 typedef enum rdma_cc_type {
106 	RDMA_CC_CLNT,	/* CONN is for a client */
107 	RDMA_CC_SRV	/* CONN is for a server */
108 } rdma_cc_type_t;
109 
110 /*
111  * Client side credit control data structure.
112  */
113 typedef struct rdma_clnt_cred_ctrl {
114 	uint32_t	clnt_cc_granted_ops;
115 	uint32_t	clnt_cc_in_flight_ops;
116 	kcondvar_t	clnt_cc_cv;
117 } rdma_clnt_cred_ctrl_t;
118 
119 /*
120  * Server side credit control data structure.
121  */
122 typedef struct rdma_srv_cred_ctrl {
123 	uint32_t	srv_cc_buffers_granted;
124 	uint32_t	srv_cc_cur_buffers_used;
125 	uint32_t	srv_cc_posted;
126 	uint32_t	srv_cc_max_buf_size;	/* to be determined by CCP */
127 	uint32_t	srv_cc_cur_buf_size;	/* to be determined by CCP */
128 } rdma_srv_cred_ctrl_t;
129 
130 typedef enum {
131     RPCCALL_WLIST,
132     RPCCALL_WCHUNK,
133     RPCCALL_NOWRITE
134 }rpccall_write_t;
135 
136 typedef enum {
137 	CLIST_REG_SOURCE = 1,
138 	CLIST_REG_DST
139 } clist_dstsrc;
140 
141 /*
142  * Return codes from RDMA operations
143  */
144 typedef enum {
145 
146 	RDMA_SUCCESS = 0,	/* successful operation */
147 
148 	RDMA_INVAL = 1,		/* invalid parameter */
149 	RDMA_TIMEDOUT = 2,	/* operation timed out */
150 	RDMA_INTR = 3,		/* operation interrupted */
151 	RDMA_NORESOURCE = 4,	/* insufficient resource */
152 	/*
153 	 * connection errors
154 	 */
155 	RDMA_REJECT = 5,	/* connection req rejected */
156 	RDMA_NOLISTENER = 6,	/* no listener on server */
157 	RDMA_UNREACHABLE = 7,	/* host unreachable */
158 	RDMA_CONNLOST = 8,	/* connection lost */
159 
160 	RDMA_XPRTFAILED = 9,	/* RDMA transport failed */
161 	RDMA_PROTECTERR = 10,	/* memory protection error */
162 	RDMA_OVERRUN = 11,	/* transport overrun */
163 	RDMA_RECVQEMPTY = 12,	/* incoming pkt dropped, recv q empty */
164 	RDMA_PROTFAILED = 13,	/* RDMA protocol failed */
165 	RDMA_NOTSUPP = 14,	/* requested feature not supported */
166 	RDMA_REMOTERR = 15,	/* error at remote end */
167 	/*
168 	 * RDMATF errors
169 	 */
170 	RDMA_BADVERS = 16,	/* mismatch RDMATF versions */
171 	RDMA_REG_EXIST = 17,	/* RDMATF registration already exists */
172 	RDMA_HCA_ATTACH = 18,
173 	RDMA_HCA_DETACH = 19,
174 
175 	/*
176 	 * fallback error
177 	 */
178 	RDMA_FAILED = 20	/* generic error */
179 } rdma_stat;
180 
181 /*
182  * Memory region context. This is an RDMA provider generated
183  * handle for a registered arbitrary size contiguous virtual
184  * memory. The RDMA Interface Adapter needs this for local or
185  * remote memory access.
186  *
187  * The mrc_rmr field holds the remote memory region context
188  * which is sent over-the-wire to provide the remote host
189  * with RDMA access to the memory region.
190  */
191 struct mrc {
192 	uint32_t	mrc_rmr;	/* Remote MR context, sent OTW */
193 	union {
194 		struct mr {
195 			uint32_t	lmr; 	/* Local MR context */
196 			uint64_t	linfo;	/* Local memory info */
197 		} mr;
198 	} lhdl;
199 };
200 
201 #define	mrc_lmr		lhdl.mr.lmr
202 #define	mrc_linfo	lhdl.mr.linfo
203 
204 /*
205  * Memory management for the RDMA buffers
206  */
207 /*
208  * RDMA buffer types
209  */
210 typedef enum {
211 	SEND_BUFFER,	/* buf for send msg */
212 	SEND_DESCRIPTOR, /* buf used for send msg descriptor in plugins only */
213 	RECV_BUFFER,	/* buf for recv msg */
214 	RECV_DESCRIPTOR, /* buf used for recv msg descriptor in plugins only */
215 	RDMA_LONG_BUFFER /* chunk buf used in RDMATF only and not in plugins */
216 } rdma_btype;
217 
218 /*
219  * RDMA buffer information
220  */
221 typedef struct rdma_buf {
222 	rdma_btype	type;	/* buffer type */
223 	uint_t		len;	/* length of buffer */
224 	caddr_t		addr;	/* buffer address */
225 	struct mrc	handle;	/* buffer registration handle */
226 	caddr_t		rb_private;
227 } rdma_buf_t;
228 
229 
230 /*
231  * The XDR offset value is used by the XDR
232  * routine to identify the position in the
233  * RPC message where the opaque object would
234  * normally occur. Neither the data content
235  * of the chunk, nor its size field are included
236  * in the RPC message.  The XDR offset is calculated
237  * as if the chunks were present.
238  *
239  * The remaining fields identify the chunk of data
240  * on the sender.  The c_memhandle identifies a
241  * registered RDMA memory region and the c_addr
242  * and c_len fields identify the chunk within it.
243  */
244 struct clist {
245 	uint32		c_xdroff;	/* XDR offset */
246 	uint32		c_len;		/* Length */
247 	clist_dstsrc	c_regtype;	/* type of registration */
248 	struct mrc	c_smemhandle;	/* src memory handle */
249 	uint64 		c_ssynchandle;	/* src sync handle */
250 	union {
251 		uint64		c_saddr;	/* src address */
252 		caddr_t 	c_saddr3;
253 	} w;
254 	struct mrc	c_dmemhandle;	/* dst memory handle */
255 	uint64		c_dsynchandle;	/* dst sync handle */
256 	union {
257 		uint64	c_daddr;	/* dst address */
258 		caddr_t	c_daddr3;
259 	} u;
260 	struct as	*c_adspc;	/* address space for saddr/daddr */
261 	rdma_buf_t	rb_longbuf;	/* used for long requests/replies */
262 	struct clist	*c_next;	/* Next chunk */
263 };
264 
265 typedef struct clist clist;
266 
267 /*
268  * max 4M wlist xfer size
269  * This is defined because the rfs3_tsize service requires
270  * svc_req struct (which we don't have that in krecv).
271  */
272 #define	MAX_SVC_XFER_SIZE (4*1024*1024)
273 
274 enum rdma_proc {
275 	RDMA_MSG	= 0,	/* chunk list and RPC msg follow */
276 	RDMA_NOMSG	= 1,	/* only chunk list follows */
277 	RDMA_MSGP	= 2,	/* chunk list and RPC msg with padding follow */
278 	RDMA_DONE	= 3	/* signal completion of chunk transfer */
279 };
280 
281 /*
282  * Listener information for a service
283  */
284 struct rdma_svc_data {
285 	queue_t		q;	/* queue_t to place incoming pkts */
286 	int		active;	/* If active, after registeration startup */
287 	rdma_stat	err_code;	/* Error code from plugin layer */
288 	int32_t		svcid;		/* RDMA based service identifier */
289 };
290 
291 /*
292  * Per RDMA plugin module information.
293  * Will be populated by each plugin
294  * module during its initialization.
295  */
296 typedef struct rdma_mod {
297 	char 		*rdma_api;		/* "kvipl", "ibtf", etc */
298 	uint_t 		rdma_version;		/* RDMATF API version */
299 	int		rdma_count;		/* # of devices */
300 	struct rdmaops 	*rdma_ops;		/* rdma op vector for api */
301 } rdma_mod_t;
302 
303 /*
304  * Registry of RDMA plugins
305  */
306 typedef struct rdma_registry {
307 	rdma_mod_t	*r_mod;		/* plugin mod info */
308 	uint32_t	r_mod_state;
309 	struct rdma_registry *r_next;	/* next registered RDMA plugin */
310 } rdma_registry_t;
311 
312 /*
313  * RDMA MODULE state flags (r_mod_state).
314  */
315 #define	RDMA_MOD_ACTIVE		1
316 #define	RDMA_MOD_INACTIVE	0
317 
318 /*
319  * RDMA transport information
320  */
321 typedef struct rdma_info {
322 	uint_t	addrlen;	/* address length */
323 	uint_t  mts;		/* max transfer size */
324 	uint_t  mtu;		/* native mtu size of unlerlying network */
325 } rdma_info_t;
326 
327 typedef enum {
328 	C_IDLE		= 0x00000001,
329 	C_CONN_PEND	= 0x00000002,
330 	C_CONNECTED	= 0x00000004,
331 	C_ERROR_CONN	= 0x00000008,
332 	C_DISCONN_PEND	= 0x00000010,
333 	C_REMOTE_DOWN	= 0x00000020
334 } conn_c_state;
335 
336 /* c_flags */
337 #define	C_CLOSE_NOTNEEDED	0x00000001	/* just free the channel */
338 #define	C_CLOSE_PENDING		0x00000002	/* a close in progress */
339 
340 /*
341  * RDMA Connection information
342  */
343 typedef struct conn {
344 	rdma_mod_t	*c_rdmamod;	/* RDMA transport info for conn */
345 	struct netbuf	c_raddr;	/* remote address */
346 	struct netbuf	c_laddr;	/* local address */
347 	int		c_ref;		/* no. of clients of connection */
348 	struct conn	*c_next;	/* next in list of connections */
349 	struct conn	*c_prev;	/* prev in list of connections */
350 	caddr_t		c_private;	/* transport specific stuff */
351 	conn_c_state	c_state;	/* state of connection */
352 	int		c_flags;	/* flags for connection management */
353 	rdma_cc_type_t	c_cc_type;	/* client or server, for credit cntrl */
354 	union {
355 		rdma_clnt_cred_ctrl_t	c_clnt_cc;
356 		rdma_srv_cred_ctrl_t	c_srv_cc;
357 	} rdma_conn_cred_ctrl_u;
358 	kmutex_t	c_lock;		/* protect c_state and c_ref fields */
359 	kcondvar_t	c_cv;		/* to signal when pending is done */
360 	timeout_id_t	c_timeout;	/* timeout id for untimeout() */
361 	time_t		c_last_used;	/* last time any activity on the conn */
362 } CONN;
363 
364 
365 /*
366  * Data transferred from plugin interrupt to svc_queuereq()
367  */
368 typedef struct rdma_recv_data {
369 	CONN		*conn;
370 	int		status;
371 	rdma_buf_t	rpcmsg;
372 } rdma_recv_data_t;
373 
374 /* structure used to pass information for READ over rdma write */
375 typedef enum {
376 	RCI_WRITE_UIO_CHUNK = 1,
377 	RCI_WRITE_ADDR_CHUNK = 2,
378 	RCI_REPLY_CHUNK = 3
379 } rci_type_t;
380 
381 typedef struct {
382 	rci_type_t rci_type;
383 	union {
384 		struct uio *rci_uiop;
385 		caddr_t    rci_addr;
386 	} rci_a;
387 	uint32	rci_len;
388 	struct clist	**rci_clpp; /* point to write chunk list in readargs */
389 } rdma_chunkinfo_t;
390 
391 typedef struct {
392 	uint_t rcil_len;
393 	uint_t rcil_len_alt;
394 } rdma_chunkinfo_lengths_t;
395 
396 typedef struct {
397 	struct	clist	*rwci_wlist;
398 	CONN		*rwci_conn;
399 } rdma_wlist_conn_info_t;
400 
401 /*
402  * Operations vector for RDMA transports.
403  */
404 typedef struct rdmaops {
405 	/* Network */
406 	rdma_stat	(*rdma_reachable)(int addr_type, struct netbuf *,
407 						void **handle);
408 	/* Connection */
409 	rdma_stat	(*rdma_get_conn)(struct netbuf *, struct netbuf *,
410 					int addr_type, void *, CONN **);
411 	rdma_stat	(*rdma_rel_conn)(CONN *);
412 	/* Server side listner start and stop routines */
413 	void		(*rdma_svc_listen)(struct rdma_svc_data *);
414 	void		(*rdma_svc_stop)(struct rdma_svc_data *);
415 	/* Memory */
416 	rdma_stat	(*rdma_regmem)(CONN *, caddr_t, caddr_t,
417 			    uint_t, struct mrc *);
418 	rdma_stat	(*rdma_deregmem)(CONN *, caddr_t, struct mrc);
419 	rdma_stat	(*rdma_regmemsync)(CONN *, caddr_t, caddr_t, uint_t,
420 				struct mrc *, void **, void *);
421 	rdma_stat	(*rdma_deregmemsync)(CONN *, caddr_t, struct mrc,
422 			    void *, void *);
423 	rdma_stat	(*rdma_syncmem)(CONN *, void *, caddr_t, int, int);
424 	/* Buffer */
425 	rdma_stat	(*rdma_buf_alloc)(CONN *, rdma_buf_t *);
426 	void		(*rdma_buf_free)(CONN *, rdma_buf_t *);
427 	/* Transfer */
428 	rdma_stat	(*rdma_send)(CONN *, clist *, uint32_t);
429 	rdma_stat	(*rdma_send_resp)(CONN *, clist *, uint32_t);
430 	rdma_stat	(*rdma_clnt_recvbuf)(CONN *, clist *, uint32_t);
431 	rdma_stat	(*rdma_clnt_recvbuf_remove)(CONN *, uint32_t);
432 	rdma_stat	(*rdma_svc_recvbuf)(CONN *, clist *);
433 	rdma_stat	(*rdma_recv)(CONN *, clist **, uint32_t);
434 	/* RDMA */
435 	rdma_stat	(*rdma_read)(CONN *, clist *, int);
436 	rdma_stat	(*rdma_write)(CONN *, clist *, int);
437 	/* INFO */
438 	rdma_stat	(*rdma_getinfo)(rdma_info_t *info);
439 } rdmaops_t;
440 
441 typedef struct rdma_svc_wait {
442 	kmutex_t svc_lock;
443 	kcondvar_t svc_cv;
444 	rdma_stat svc_stat;
445 } rdma_svc_wait_t;
446 
447 extern rdma_svc_wait_t rdma_wait;
448 
449 /*
450  * RDMA operations.
451  */
452 #define	RDMA_REACHABLE(rdma_ops, addr_type, addr, handle)	\
453 	(*(rdma_ops)->rdma_reachable)(addr_type, addr, handle)
454 
455 #define	RDMA_GET_CONN(rdma_ops, saddr, daddr, addr_type, handle, conn)	\
456 	(*(rdma_ops)->rdma_get_conn)(saddr, daddr, addr_type, handle, conn)
457 
458 #define	RDMA_REL_CONN(conn)	\
459 	(*(conn)->c_rdmamod->rdma_ops->rdma_rel_conn)(conn)
460 
461 #define	RDMA_REGMEM(conn, adsp, buff, len, handle)	\
462 	(*(conn)->c_rdmamod->rdma_ops->rdma_regmem)(conn, adsp,	\
463 		buff, len, handle)
464 
465 #define	RDMA_DEREGMEM(conn, buff, handle)	\
466 	(*(conn)->c_rdmamod->rdma_ops->rdma_deregmem)(conn, buff, handle)
467 
468 #define	RDMA_REGMEMSYNC(conn, adsp, buff, len, handle, synchandle, lrc)	\
469 	(*(conn)->c_rdmamod->rdma_ops->rdma_regmemsync)(conn, adsp, buff, \
470 	len, handle, synchandle, lrc)
471 
472 #define	RDMA_DEREGMEMSYNC(conn, buff, handle, synchandle, lrc)	\
473 	(*(conn)->c_rdmamod->rdma_ops->rdma_deregmemsync)(conn, buff,	\
474 	handle, synchandle, lrc)
475 
476 #define	RDMA_SYNCMEM(conn, handle, buff, len, direction)	\
477 	(*(conn)->c_rdmamod->rdma_ops->rdma_syncmem)(conn, handle, \
478 	    buff, len, direction)
479 
480 #define	RDMA_BUF_ALLOC(conn, rbuf)	\
481 	(*(conn)->c_rdmamod->rdma_ops->rdma_buf_alloc)(conn, rbuf)
482 
483 #define	RDMA_BUF_FREE(conn, rbuf)	\
484 	(*(conn)->c_rdmamod->rdma_ops->rdma_buf_free)(conn, rbuf)
485 
486 #define	RDMA_SEND(conn, sendlist, xid)	\
487 	(*(conn)->c_rdmamod->rdma_ops->rdma_send)(conn, sendlist, xid)
488 
489 #define	RDMA_SEND_RESP(conn, sendlist, xid)	\
490 	(*(conn)->c_rdmamod->rdma_ops->rdma_send_resp)(conn, sendlist, xid)
491 
492 #define	RDMA_CLNT_RECVBUF(conn, cl, xid)	\
493 	(*(conn)->c_rdmamod->rdma_ops->rdma_clnt_recvbuf)(conn, cl, xid)
494 
495 #define	RDMA_CLNT_RECVBUF_REMOVE(conn, xid)	\
496 	(*(conn)->c_rdmamod->rdma_ops->rdma_clnt_recvbuf_remove)(conn, xid)
497 
498 #define	RDMA_SVC_RECVBUF(conn, cl)	\
499 	(*(conn)->c_rdmamod->rdma_ops->rdma_svc_recvbuf)(conn, cl)
500 
501 #define	RDMA_RECV(conn, recvlist, xid)	\
502 	(*(conn)->c_rdmamod->rdma_ops->rdma_recv)(conn, recvlist, xid)
503 
504 #define	RDMA_READ(conn, cl, wait)	\
505 	(*(conn)->c_rdmamod->rdma_ops->rdma_read)(conn, cl, wait)
506 
507 #define	RDMA_WRITE(conn, cl, wait)	\
508 	(*(conn)->c_rdmamod->rdma_ops->rdma_write)(conn, cl, wait)
509 
510 #define	RDMA_GETINFO(rdma_mod, info)	\
511 	(*(rdma_mod)->rdma_ops->rdma_getinfo)(info)
512 
513 #ifdef _KERNEL
514 extern rdma_registry_t	*rdma_mod_head;
515 extern krwlock_t rdma_lock;		/* protects rdma_mod_head list */
516 extern int rdma_modloaded;		/* flag for loading RDMA plugins */
517 extern int rdma_dev_available;		/* rdma device is loaded or not */
518 extern kmutex_t rdma_modload_lock;	/* protects rdma_modloaded flag */
519 extern uint_t rdma_minchunk;
520 extern ldi_ident_t rpcmod_li; 		/* needed by layed driver framework */
521 
522 /*
523  * General RDMA routines
524  */
525 extern struct clist *clist_alloc(void);
526 extern void clist_add(struct clist **, uint32_t, int,
527 	struct mrc *, caddr_t, struct mrc *, caddr_t);
528 extern void clist_free(struct clist *);
529 extern uint32_t clist_len(struct clist *);
530 extern void clist_zero_len(struct clist *);
531 extern rdma_stat clist_register(CONN *conn, struct clist *cl, clist_dstsrc);
532 extern rdma_stat clist_deregister(CONN *conn, struct clist *cl);
533 extern rdma_stat clist_syncmem(CONN *conn, struct clist *cl, clist_dstsrc);
534 extern rdma_stat rdma_clnt_postrecv(CONN *conn, uint32_t xid);
535 extern rdma_stat rdma_clnt_postrecv_remove(CONN *conn, uint32_t xid);
536 extern rdma_stat rdma_svc_postrecv(CONN *conn);
537 extern rdma_stat rdma_register_mod(rdma_mod_t *mod);
538 extern rdma_stat rdma_unregister_mod(rdma_mod_t *mod);
539 extern rdma_stat rdma_buf_alloc(CONN *, rdma_buf_t *);
540 extern void rdma_buf_free(CONN *, rdma_buf_t *);
541 extern int rdma_modload();
542 extern bool_t   rdma_get_wchunk(struct svc_req *, iovec_t *, struct clist *);
543 extern rdma_stat rdma_kwait(void);
544 extern int rdma_setup_read_chunks(struct clist *, uint32_t, int *);
545 
546 /*
547  * RDMA XDR
548  */
549 extern void xdrrdma_create(XDR *, caddr_t, uint_t, int, struct clist *,
550 	enum xdr_op, CONN *);
551 extern void xdrrdma_destroy(XDR *);
552 
553 extern uint_t xdrrdma_getpos(XDR *);
554 extern bool_t xdrrdma_setpos(XDR *, uint_t);
555 extern bool_t xdr_clist(XDR *, clist *);
556 extern bool_t xdr_do_clist(XDR *, clist **);
557 extern uint_t xdr_getbufsize(XDR *);
558 extern unsigned int xdrrdma_sizeof(xdrproc_t, void *, int, uint_t *, uint_t *);
559 extern unsigned int xdrrdma_authsize(AUTH *, struct cred *, int);
560 
561 extern void xdrrdma_store_wlist(XDR *, struct clist *);
562 extern struct clist *xdrrdma_wclist(XDR *);
563 extern bool_t xdr_decode_reply_wchunk(XDR *, struct clist **);
564 extern bool_t xdr_decode_wlist(XDR *xdrs, struct clist **, bool_t *);
565 extern bool_t xdr_decode_wlist_svc(XDR *xdrs, struct clist **, bool_t *,
566 	uint32_t *, CONN *);
567 extern bool_t xdr_encode_rlist_svc(XDR *, clist *);
568 extern bool_t xdr_encode_wlist(XDR *, clist *);
569 extern bool_t xdr_encode_reply_wchunk(XDR *, struct clist *,
570 		uint32_t seg_array_len);
571 bool_t xdrrdma_getrdmablk(XDR *, struct clist **, uint_t *,
572 	CONN **conn, const uint_t);
573 bool_t xdrrdma_read_from_client(struct clist *, CONN **, uint_t);
574 bool_t xdrrdma_send_read_data(XDR *, uint_t, struct clist *);
575 bool_t xdrrdma_free_clist(CONN *, struct clist *);
576 #endif /* _KERNEL */
577 
578 #ifdef __cplusplus
579 }
580 #endif
581 
582 #endif	/* _RPC_RPC_RDMA_H */
583