Whamcloud - gitweb
LU-1347 build: remove the vim/emacs modelines
[fs/lustre-release.git] / lnet / klnds / mxlnd / mxlnd.h
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (C) 2006 Myricom, Inc.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lnet/klnds/mxlnd/mxlnd.h
37  *
38  * Author: Eric Barton <eric@bartonsoftware.com>
39  * Author: Scott Atchley <atchley at myri.com>
40  */
41
42 #ifndef EXPORT_SYMTAB
43 #define EXPORT_SYMTAB
44 #endif
45 #ifndef AUTOCONF_INCLUDED
46 #include <linux/config.h>
47 #endif
48 #include <linux/module.h>       /* module */
49 #include <linux/kernel.h>       /* module */
50 #include <linux/mm.h>
51 #include <linux/string.h>
52 #include <linux/stat.h>
53 #include <linux/errno.h>
54 #include <linux/smp_lock.h>
55 #include <linux/unistd.h>
56 #include <linux/uio.h>
57 #include <linux/fs.h>
58
59 #include <asm/system.h>
60 #include <asm/uaccess.h>
61 #include <asm/io.h>
62
63 #include <linux/init.h>         /* module */
64 #include <linux/fs.h>
65 #include <linux/file.h>
66 #include <linux/stat.h>
67 #include <linux/list.h>
68 #include <linux/kmod.h>
69 #include <linux/sysctl.h>
70 #include <linux/random.h>
71 #include <linux/utsname.h>
72 #include <linux/jiffies.h>      /* msecs_to_jiffies */
73 #include <asm/semaphore.h>
74
75 #include <net/sock.h>
76 #include <linux/in.h>
77
78 #include <asm/byteorder.h>      /* __LITTLE_ENDIAN */
79 #include <net/arp.h>            /* arp table */
80 #include <linux/netdevice.h>    /* get_device_by_name */
81 #include <linux/inetdevice.h>   /* neigh_lookup, etc. */
82 #include <linux/net.h>          /* sock_create_kern, kernel_connect, sock_release */
83
84 #define DEBUG_SUBSYSTEM S_LND
85
86 #include "libcfs/libcfs.h"
87 #include "lnet/lnet.h"
88 #include "lnet/lib-lnet.h"
89 //#include <lnet/lnet-sysctl.h>
90
91 #define MX_KERNEL 1
92 #include "mx_extensions.h"
93 #include "myriexpress.h"
94
95 #if LNET_MAX_IOV > MX_MAX_SEGMENTS
96     #error LNET_MAX_IOV is greater then MX_MAX_SEGMENTS
97 #endif
98
99 #define MXLND_MSG_MAGIC         0x4d583130              /* unique magic 'MX10' */
100 #define MXLND_MSG_VERSION       0x03
101
102 /* Using MX's 64 match bits
103  * We are using the match bits to specify message type and the cookie.  The
104  * highest four bits (60-63) are reserved for message type. Below we specify
105  * the types. We reserve the remaining combinations for future use.  The next 8
106  * bits (52-59) are reserved for returning a status code for failed GET_DATA
107  * (payload) messages. The last 52 bits are used for cookies. That should allow
108  * unique cookies for 4 KB messages at 10 Gbps line rate without rollover for
109  * about 8 years. That should be enough. */
110
111 #define MXLND_MSG_OFFSET        60      /* msg type offset */
112 #define MXLND_MSG_BITS          (64 - MXLND_MSG_OFFSET)
113 #define MXLND_MSG_MASK          (((1ULL<<MXLND_MSG_BITS) - 1) << MXLND_MSG_OFFSET)
114 #define MXLND_MSG_TYPE(x)       (((x) & MXLND_MSG_MASK) >> MXLND_MSG_OFFSET)
115
116 #define MXLND_ERROR_OFFSET      52      /* error value offset */
117 #define MXLND_ERROR_BITS        (MXLND_MSG_OFFSET - MXLND_ERROR_OFFSET)
118 #define MXLND_ERROR_MASK        (((1ULL<<MXLND_ERROR_BITS) - 1) << MXLND_ERROR_OFFSET)
119 #define MXLND_ERROR_VAL(x)      (((x) & MXLND_ERROR_MASK) >> MXLND_ERROR_OFFSET)
120
121 /* message types */
122 #define MXLND_MSG_ICON_REQ      0xb     /* mx_iconnect() before CONN_REQ */
123 #define MXLND_MSG_CONN_REQ      0xc     /* connection request */
124 #define MXLND_MSG_ICON_ACK      0x9     /* mx_iconnect() before CONN_ACK */
125 #define MXLND_MSG_CONN_ACK      0xa     /* connection request response */
126 #define MXLND_MSG_BYE           0xd     /* disconnect msg */
127 #define MXLND_MSG_EAGER         0xe     /* eager message */
128 #define MXLND_MSG_NOOP          0x1     /* no msg, return credits */
129 #define MXLND_MSG_PUT_REQ       0x2     /* put request src->sink */
130 #define MXLND_MSG_PUT_ACK       0x3     /* put ack     src<-sink */
131 #define MXLND_MSG_PUT_DATA      0x4     /* put payload src->sink */
132 #define MXLND_MSG_GET_REQ       0x5     /* get request sink->src */
133 #define MXLND_MSG_GET_DATA      0x6     /* get payload sink<-src */
134
135 /* when to roll-over the cookie value */
136 #define MXLND_MAX_COOKIE        ((1ULL << MXLND_ERROR_OFFSET) - 1)
137
138 /* defaults for configurable parameters */
139 #define MXLND_N_SCHED           1               /* # schedulers (mx_wait_any() threads) */
140 #define MXLND_NDAEMONS          3               /* connd, timeoutd, tx_queued */
141 #define MXLND_MX_BOARD          0               /* Use the first MX NIC if more than 1 avail */
142 #define MXLND_MX_EP_ID          0               /* MX endpoint ID */
143 #define MXLND_COMM_TIMEOUT      (20 * CFS_HZ)   /* timeout for send/recv (jiffies) */
144 #define MXLND_WAIT_TIMEOUT      CFS_HZ          /* timeout for wait (jiffies) */
145 #define MXLND_CONNECT_TIMEOUT   (5 * CFS_HZ)    /* timeout for connections (jiffies) */
146 #define MXLND_POLLING           1000            /* poll iterations before blocking */
147 #define MXLND_LOOKUP_COUNT      5               /* how many times to try to resolve MAC */
148 #define MXLND_MAX_PEERS         1024            /* number of nodes talking to me */
149
150 #define MXLND_MSG_SIZE          (4<<10)         /* pre-posted eager message size */
151 #define MXLND_MSG_QUEUE_DEPTH   8               /* default msg queue depth */
152 #define MXLND_NTX               256             /* default # of tx msg descriptors */
153
154 #define MXLND_HASH_BITS         6               /* the number of bits to hash over */
155 #define MXLND_HASH_SIZE         (1<<MXLND_HASH_BITS)
156                                                 /* number of peer lists for lookup.
157                                                    we hash over the last N bits of
158                                                    the IP address converted to an int. */
159 #define MXLND_HASH_MASK         (MXLND_HASH_SIZE - 1)
160                                                 /* ensure we use only the last N bits */
161
162 /* derived constants... */
163 /* TX messages (shared by all connections) */
164 #define MXLND_TX_MSGS()       (*kmxlnd_tunables.kmx_ntx)
165 #define MXLND_TX_MSG_BYTES()  (MXLND_TX_MSGS() * MXLND_MSG_SIZE)
166 #define MXLND_TX_MSG_PAGES()  ((MXLND_TX_MSG_BYTES() + PAGE_SIZE - 1)/PAGE_SIZE)
167
168 /* RX messages (per connection) */
169 #define MXLND_RX_MSGS()       (*kmxlnd_tunables.kmx_peercredits)
170 #define MXLND_RX_MSG_BYTES()  (MXLND_RX_MSGS() * MXLND_MSG_SIZE)
171 #define MXLND_RX_MSG_PAGES()  ((MXLND_RX_MSG_BYTES() + PAGE_SIZE - 1)/PAGE_SIZE)
172 #define MXLND_CREDIT_HIGHWATER() (*kmxlnd_tunables.kmx_peercredits - 2)
173                                                 /* when to send a noop to return credits */
174
175 /* debugging features */
176 #define MXLND_CKSUM             0       /* checksum kmx_msg_t */
177 #define MXLND_DEBUG             0       /* additional CDEBUG messages */
178
179 /* provide wrappers around LIBCFS_ALLOC/FREE to keep MXLND specific
180  * memory usage stats that include pages */
181
182 #define MXLND_ALLOC(x, size) \
183         do { \
184                 cfs_spin_lock(&kmxlnd_data.kmx_mem_lock); \
185                 kmxlnd_data.kmx_mem_used += size; \
186                 cfs_spin_unlock(&kmxlnd_data.kmx_mem_lock); \
187                 LIBCFS_ALLOC(x, size); \
188                 if (unlikely(x == NULL)) { \
189                         cfs_spin_lock(&kmxlnd_data.kmx_mem_lock); \
190                         kmxlnd_data.kmx_mem_used -= size; \
191                         cfs_spin_unlock(&kmxlnd_data.kmx_mem_lock); \
192                 } \
193         } while (0)
194
195 #define MXLND_FREE(x, size) \
196         do { \
197                 cfs_spin_lock(&kmxlnd_data.kmx_mem_lock); \
198                 kmxlnd_data.kmx_mem_used -= size; \
199                 cfs_spin_unlock(&kmxlnd_data.kmx_mem_lock); \
200                 LIBCFS_FREE(x, size); \
201         } while (0)
202
203
204 typedef struct kmx_tunables
205 {
206         int     *kmx_n_waitd;           /* # completion threads */
207         int     *kmx_max_peers;         /* max # of potential peers */
208         int     *kmx_cksum;             /* checksum small msgs? */
209         int     *kmx_ntx;               /* total # of tx */
210         int     *kmx_credits;           /* concurrent sends to all peers */
211         int     *kmx_peercredits;       /* concurrent sends to 1 peer */
212         int     *kmx_board;             /* MX board (NIC) number */
213         int     *kmx_ep_id;             /* MX endpoint number */
214         char    **kmx_default_ipif;     /* IPoMX interface name */
215         int     *kmx_polling;           /* if 0, block. if > 0, poll this many
216                                            iterations before blocking */
217 } kmx_tunables_t;
218
219 typedef struct
220 {
221         int               mxg_npages;   /* # pages */
222         struct page      *mxg_pages[0];
223 } kmx_pages_t;
224
225 /* global interface state */
226 typedef struct kmx_data
227 {
228         int                 kmx_init;           /* initialization state */
229         cfs_atomic_t        kmx_shutdown;       /* shutting down? */
230         cfs_atomic_t        kmx_nthreads;       /* number of threads */
231         cfs_completion_t   *kmx_completions;   /* array of completion structs */
232         lnet_ni_t          *kmx_ni;             /* the LND instance */
233         u64                 kmx_incarnation;    /* my incarnation value */
234         long                kmx_mem_used;       /* memory used */
235         mx_endpoint_t       kmx_endpt;          /* the MX endpoint */
236         mx_endpoint_addr_t  kmx_epa;            /* the MX endpoint address */
237
238         cfs_rwlock_t        kmx_global_lock;    /* global lock */
239         cfs_spinlock_t      kmx_mem_lock;       /* memory accounting lock */
240
241         cfs_list_t          kmx_conn_reqs;     /* list of connection requests */
242         cfs_spinlock_t      kmx_conn_lock;      /* connection list lock */
243         cfs_semaphore_t     kmx_conn_sem;       /* semaphore for connection request list */
244         cfs_list_t          kmx_conn_zombies;   /* list of zombie connections */
245         cfs_list_t          kmx_orphan_msgs;    /* list of txs to cancel */
246
247                                                 /* list of all known peers */
248         cfs_list_t          kmx_peers[MXLND_HASH_SIZE];
249         cfs_atomic_t        kmx_npeers;         /* number of peers */
250
251         kmx_pages_t        *kmx_tx_pages;       /* tx msg pages */
252
253         struct kmx_ctx     *kmx_txs;            /* all tx descriptors */
254         cfs_list_t          kmx_tx_idle;        /* list of idle tx */
255         cfs_spinlock_t      kmx_tx_idle_lock;   /* lock for idle tx list */
256         s32                 kmx_tx_used;        /* txs in use */
257         u64                 kmx_tx_next_cookie; /* unique id for tx */
258         cfs_list_t          kmx_tx_queue;       /* generic send queue */
259         cfs_spinlock_t      kmx_tx_queue_lock;  /* lock for generic sends */
260         cfs_semaphore_t     kmx_tx_queue_sem;   /* semaphore for tx queue */
261 } kmx_data_t;
262
263 #define MXLND_INIT_NOTHING      0       /* in the beginning, there was nothing... */
264 #define MXLND_INIT_DATA         1       /* main data structures created */
265 #define MXLND_INIT_TXS          2       /* tx descriptors created */
266 #define MXLND_INIT_MX           3       /* initiate MX library, open endpoint, get NIC id */
267 #define MXLND_INIT_THREADS      4       /* waitd, timeoutd, tx_queued threads */
268 #define MXLND_INIT_ALL          5       /* startup completed */
269
270 /************************************************************************
271  * MXLND Wire message format.
272  * These are sent in sender's byte order (i.e. receiver flips).
273  */
274
275 typedef struct kmx_connreq_msg
276 {
277         u32             mxcrm_queue_depth;              /* per peer max messages in flight */
278         u32             mxcrm_eager_size;               /* size of preposted eager messages */
279 } WIRE_ATTR kmx_connreq_msg_t;
280
281 typedef struct kmx_eager_msg
282 {
283         lnet_hdr_t      mxem_hdr;                       /* lnet header */
284         char            mxem_payload[0];                /* piggy-backed payload */
285 } WIRE_ATTR kmx_eager_msg_t;
286
287 typedef struct kmx_putreq_msg
288 {
289         lnet_hdr_t      mxprm_hdr;                      /* lnet header */
290         u64             mxprm_cookie;                   /* opaque completion cookie */
291 } WIRE_ATTR kmx_putreq_msg_t;
292
293 typedef struct kmx_putack_msg
294 {
295         u64             mxpam_src_cookie;               /* reflected completion cookie */
296         u64             mxpam_dst_cookie;               /* opaque completion cookie */
297 } WIRE_ATTR kmx_putack_msg_t;
298
299 typedef struct kmx_getreq_msg
300 {
301         lnet_hdr_t      mxgrm_hdr;                      /* lnet header */
302         u64             mxgrm_cookie;                   /* opaque completion cookie */
303 } WIRE_ATTR kmx_getreq_msg_t;
304
305 typedef struct kmx_msg
306 {
307         /* First two fields fixed for all time */
308         u32             mxm_magic;                      /* MXLND message */
309         u16             mxm_version;                    /* version number */
310
311         u8              mxm_type;                       /* message type */
312         u8              mxm_credits;                    /* returned credits */
313         u32             mxm_nob;                        /* # of bytes in whole message */
314         u32             mxm_cksum;                      /* checksum (0 == no checksum) */
315         u64             mxm_srcnid;                     /* sender's NID */
316         u64             mxm_srcstamp;                   /* sender's incarnation */
317         u64             mxm_dstnid;                     /* destination's NID */
318         u64             mxm_dststamp;                   /* destination's incarnation */
319
320         union {
321                 kmx_connreq_msg_t       conn_req;
322                 kmx_eager_msg_t         eager;
323                 kmx_putreq_msg_t        put_req;
324                 kmx_putack_msg_t        put_ack;
325                 kmx_getreq_msg_t        get_req;
326         } WIRE_ATTR mxm_u;
327 } WIRE_ATTR kmx_msg_t;
328
329 /***********************************************************************/
330
331 enum kmx_req_type {
332         MXLND_REQ_TX    = 0,
333         MXLND_REQ_RX    = 1,
334 };
335
336 /* The life cycle of a request */
337 enum kmx_req_state {
338         MXLND_CTX_INIT       = 0,               /* just created */
339         MXLND_CTX_IDLE       = 1,               /* available for use */
340         MXLND_CTX_PREP       = 2,               /* getting ready for send/recv */
341         MXLND_CTX_PENDING    = 3,               /* mx_isend() or mx_irecv() called */
342         MXLND_CTX_COMPLETED  = 4,               /* cleaning up after completion or timeout */
343         MXLND_CTX_CANCELED   = 5,               /* timed out but still in ctx list */
344 };
345
346 /* Context Structure - generic tx/rx descriptor
347  * It represents the context (or state) of each send or receive request.
348  * In other LNDs, they have separate TX and RX descriptors and this replaces both.
349  *
350  * The txs live on the global kmx_txs array for cleanup. The rxs are managed
351  * per struct kmx_conn. We will move them between the rx/tx idle lists and the
352  * pending list which is monitored by mxlnd_timeoutd().
353  */
354 typedef struct kmx_ctx
355 {
356         enum kmx_req_type   mxc_type;           /* TX or RX */
357         u64                 mxc_incarnation;    /* store the peer's incarnation here
358                                                    to verify before changing flow
359                                                    control credits after completion */
360         unsigned long       mxc_deadline;       /* request time out in absolute jiffies */
361         enum kmx_req_state  mxc_state;          /* what is the state of the request? */
362         cfs_list_t          mxc_list;           /* place on rx/tx idle list, tx q, peer tx */
363         cfs_list_t          mxc_rx_list;        /* place on mxp_rx_posted list */
364
365         lnet_nid_t          mxc_nid;            /* dst's NID if peer is not known */
366         struct kmx_peer    *mxc_peer;           /* owning peer */
367         struct kmx_conn    *mxc_conn;           /* owning conn */
368         kmx_msg_t          *mxc_msg;            /* msg hdr mapped to mxc_page */
369         lnet_msg_t         *mxc_lntmsg[2];      /* lnet msgs to finalize */
370
371         u8                  mxc_msg_type;       /* what type of message is this? */
372         u64                 mxc_cookie;         /* completion cookie */
373         u64                 mxc_match;          /* MX match info */
374         mx_ksegment_t       mxc_seg;            /* local MX ksegment for non-DATA */
375         mx_ksegment_t      *mxc_seg_list;       /* MX ksegment array for DATA */
376         int                 mxc_nseg;           /* number of segments */
377         unsigned long       mxc_pin_type;       /* MX_PIN_PHYSICAL [| MX_PIN_FULLPAGES] */
378         u32                 mxc_nob;            /* number of bytes sent/received */
379         mx_request_t        mxc_mxreq;          /* MX request */
380         mx_status_t         mxc_status;         /* MX status */
381         u32                 mxc_errno;          /* errno for LNET */
382         u64                 mxc_get;            /* # of times returned from idle list */
383         u64                 mxc_put;            /* # of times returned from idle list */
384 } kmx_ctx_t;
385
386 #define MXLND_CONN_DISCONNECT  -2       /* conn is being destroyed - do not add txs */
387 #define MXLND_CONN_FAIL        -1       /* connect failed (bad handshake, unavail, etc.) */
388 #define MXLND_CONN_INIT         0       /* in the beginning, there was nothing... */
389 #define MXLND_CONN_REQ          1       /* a connection request message is needed */
390 #define MXLND_CONN_ACK          2       /* a connection ack is needed */
391 #define MXLND_CONN_WAIT         3       /* waiting for req or ack to complete */
392 #define MXLND_CONN_READY        4       /* ready to send */
393
394 /* store all data from an unexpected CONN_[REQ|ACK] receive */
395 typedef struct kmx_connparams
396 {
397         cfs_list_t              mxr_list;       /* list to hang on kmx_conn_reqs */
398         void                   *mxr_context;    /* context - unused - will hold net */
399         mx_endpoint_addr_t      mxr_epa;        /* the peer's epa */
400         u64                     mxr_match;      /* the CONN_REQ's match bits */
401         u32                     mxr_nob;        /* length of CONN_REQ message */
402         struct kmx_peer        *mxr_peer;       /* peer if known */
403         struct kmx_conn        *mxr_conn;       /* conn if known */
404         kmx_msg_t               mxr_msg;        /* the msg header & connreq_msg_t */
405 } kmx_connparams_t;
406
407 /* connection state - queues for queued and pending msgs */
408 typedef struct kmx_conn
409 {
410         struct kmx_peer    *mxk_peer;           /* owning peer */
411         cfs_list_t          mxk_list;           /* for placing on mxp_conns */
412         cfs_list_t          mxk_zombie;         /* for placing on zombies list */
413         u64                 mxk_incarnation;    /* connections's incarnation value */
414         u32                 mxk_sid;            /* peer's MX session id */
415         cfs_atomic_t        mxk_refcount;       /* reference counting */
416         int                 mxk_status;         /* can we send messages? MXLND_CONN_* */
417
418         mx_endpoint_addr_t  mxk_epa;            /* peer's endpoint address */
419
420         cfs_spinlock_t      mxk_lock;           /* lock */
421         unsigned long       mxk_timeout;        /* expiration of oldest pending tx/rx */
422         unsigned long       mxk_last_tx;        /* when last tx completed with success */
423         unsigned long       mxk_last_rx;        /* when last rx completed */
424
425         kmx_pages_t        *mxk_rx_pages;       /* rx msg pages */
426         kmx_ctx_t          *mxk_rxs;            /* the rx descriptors */
427         cfs_list_t          mxk_rx_idle;        /* list of idle rx */
428
429         int                 mxk_credits;        /* # of my credits for sending to peer */
430         int                 mxk_outstanding;    /* # of credits to return */
431
432         cfs_list_t          mxk_tx_credit_queue; /* send queue for peer */
433         cfs_list_t          mxk_tx_free_queue;  /* send queue for peer */
434         int                 mxk_ntx_msgs;       /* # of msgs on tx queues */
435         int                 mxk_ntx_data ;      /* # of DATA on tx queues */
436         int                 mxk_ntx_posted;     /* # of tx msgs in flight */
437         int                 mxk_data_posted;    /* # of tx data payloads in flight */
438
439         cfs_list_t          mxk_pending;        /* in flight rxs and txs */
440 } kmx_conn_t;
441
442 /* peer state */
443 typedef struct kmx_peer
444 {
445         cfs_list_t          mxp_list;           /* for placing on kmx_peers */
446         lnet_nid_t          mxp_nid;            /* peer's LNET NID */
447         lnet_ni_t          *mxp_ni;             /* LNET interface */
448         cfs_atomic_t        mxp_refcount;       /* reference counts */
449
450         cfs_list_t          mxp_conns;          /* list of connections */
451         kmx_conn_t         *mxp_conn;           /* current connection */
452         cfs_list_t          mxp_tx_queue;       /* msgs waiting for a conn */
453
454         u32                 mxp_board;          /* peer's board rank */
455         u32                 mxp_ep_id;          /* peer's MX endpoint ID */
456         u64                 mxp_nic_id;         /* remote's MX nic_id for mx_connect() */
457
458         unsigned long       mxp_reconnect_time; /* when to retry connect */
459         int                 mxp_incompatible;   /* incorrect conn_req values */
460 } kmx_peer_t;
461
462 extern kmx_data_t       kmxlnd_data;
463 extern kmx_tunables_t   kmxlnd_tunables;
464
465 /* required for the LNET API */
466 int  mxlnd_startup(lnet_ni_t *ni);
467 void mxlnd_shutdown(lnet_ni_t *ni);
468 int  mxlnd_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg);
469 int  mxlnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg);
470 int  mxlnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed,
471                 unsigned int niov, struct iovec *iov, lnet_kiov_t *kiov,
472                 unsigned int offset, unsigned int mlen, unsigned int rlen);
473
474 /* in mxlnd.c */
475 extern void mxlnd_thread_stop(long id);
476 extern void mxlnd_ctx_init(kmx_ctx_t *ctx);
477 extern int  mxlnd_peer_alloc(kmx_peer_t **peerp, lnet_nid_t nid,
478                 u32 board, u32 ep_id, u64 nic_id);
479 extern int mxlnd_alloc_pages(kmx_pages_t **pp, int npages);
480 extern void mxlnd_free_pages(kmx_pages_t *p);
481
482 /* in mxlnd_cb.c */
483 void mxlnd_eager_recv(void *context, uint64_t match_value, uint32_t length);
484 extern mx_unexp_handler_action_t mxlnd_unexpected_recv(void *context,
485                 mx_endpoint_addr_t source, uint64_t match_value, uint32_t length,
486                 void *data_if_available);
487 extern void mxlnd_peer_free(kmx_peer_t *peer);
488 extern void mxlnd_conn_free_locked(kmx_conn_t *conn);
489 extern void mxlnd_conn_disconnect(kmx_conn_t *conn, int mx_dis, int send_bye);
490 extern int mxlnd_close_matching_conns(lnet_nid_t nid);
491 extern void mxlnd_sleep(unsigned long timeout);
492 extern int  mxlnd_tx_queued(void *arg);
493 extern void mxlnd_handle_rx_completion(kmx_ctx_t *rx);
494 extern int  mxlnd_check_sends(kmx_peer_t *peer);
495 extern int  mxlnd_tx_peer_queued(void *arg);
496 extern int  mxlnd_request_waitd(void *arg);
497 extern int  mxlnd_unex_recvd(void *arg);
498 extern int  mxlnd_timeoutd(void *arg);
499 extern int mxlnd_free_conn_zombies(void);
500 extern int  mxlnd_connd(void *arg);
501 extern int mxlnd_del_peer(lnet_nid_t nid);
502
503
504 /**
505  * mxlnd_nid_to_hash - hash the nid
506  * @nid - LNET ID
507  *
508  * Takes the u64 nid and XORs the lowest N bits by the next lowest N bits.
509  */
510 static inline int
511 mxlnd_nid_to_hash(lnet_nid_t nid)
512 {
513         return (nid & MXLND_HASH_MASK) ^
514                ((nid & (MXLND_HASH_MASK << MXLND_HASH_BITS)) >> MXLND_HASH_BITS);
515 }
516
517
518 #define mxlnd_peer_addref(peer)                                 \
519 do {                                                            \
520         LASSERT(peer != NULL);                                  \
521         LASSERT(cfs_atomic_read(&(peer)->mxp_refcount) > 0);    \
522         cfs_atomic_inc(&(peer)->mxp_refcount);                  \
523 } while (0)
524
525
526 #define mxlnd_peer_decref(peer)                                 \
527 do {                                                            \
528         LASSERT(cfs_atomic_read(&(peer)->mxp_refcount) > 0);    \
529         if (cfs_atomic_dec_and_test(&(peer)->mxp_refcount))     \
530                 mxlnd_peer_free(peer);                          \
531 } while (0)
532
533 #define mxlnd_conn_addref(conn)                                 \
534 do {                                                            \
535         LASSERT(conn != NULL);                                  \
536         LASSERT(cfs_atomic_read(&(conn)->mxk_refcount) > 0);    \
537         cfs_atomic_inc(&(conn)->mxk_refcount);                  \
538 } while (0)
539
540
541 #define mxlnd_conn_decref(conn)                                       \
542 do {                                                                  \
543         LASSERT(conn != NULL);                                        \
544         LASSERT(cfs_atomic_read(&(conn)->mxk_refcount) > 0);          \
545         if (cfs_atomic_dec_and_test(&(conn)->mxk_refcount)) {         \
546                 cfs_spin_lock(&kmxlnd_data.kmx_conn_lock);            \
547                 LASSERT((conn)->mxk_status == MXLND_CONN_DISCONNECT); \
548                 CDEBUG(D_NET, "adding conn %p to zombies\n", (conn)); \
549                 cfs_list_add_tail(&(conn)->mxk_zombie,                \
550                                   &kmxlnd_data.kmx_conn_zombies);     \
551                 cfs_spin_unlock(&kmxlnd_data.kmx_conn_lock);          \
552                 cfs_up(&kmxlnd_data.kmx_conn_sem);                    \
553         }                                                             \
554 } while (0)
555
556 #define mxlnd_valid_msg_type(type)                              \
557 do {                                                            \
558         LASSERT((type) == MXLND_MSG_EAGER    ||                 \
559                 (type) == MXLND_MSG_ICON_REQ ||                 \
560                 (type) == MXLND_MSG_CONN_REQ ||                 \
561                 (type) == MXLND_MSG_ICON_ACK ||                 \
562                 (type) == MXLND_MSG_CONN_ACK ||                 \
563                 (type) == MXLND_MSG_BYE      ||                 \
564                 (type) == MXLND_MSG_NOOP     ||                 \
565                 (type) == MXLND_MSG_PUT_REQ  ||                 \
566                 (type) == MXLND_MSG_PUT_ACK  ||                 \
567                 (type) == MXLND_MSG_PUT_DATA ||                 \
568                 (type) == MXLND_MSG_GET_REQ  ||                 \
569                 (type) == MXLND_MSG_GET_DATA);                  \
570 } while (0)