Whamcloud - gitweb
convert uint64_t to __u64
[fs/lustre-release.git] / lnet / klnds / qswlnd / qswlnd.h
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2001 Cluster File Systems, Inc. <braam@clusterfs.com>
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  * Basic library routines.
22  *
23  */
24
25 #ifndef _QSWNAL_H
26 #define _QSWNAL_H
27 #ifndef EXPORT_SYMTAB
28 # define EXPORT_SYMTAB
29 #endif
30
31 #include <qsnet/kernel.h>
32 #undef printf                                   /* nasty QSW #define */
33 #ifndef AUTOCONF_INCLUDED
34 #include <linux/config.h>
35 #endif
36 #include <linux/module.h>
37
38 #include <elan/epcomms.h>
39
40 #include <linux/kernel.h>
41 #include <linux/mm.h>
42 #include <linux/string.h>
43 #include <linux/stat.h>
44 #include <linux/errno.h>
45 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
46 #include <linux/locks.h>        /* wait_on_buffer */
47 #else
48 #include <linux/buffer_head.h>  /* wait_on_buffer */
49 #endif
50 #include <linux/unistd.h>
51 #include <net/sock.h>
52 #include <linux/uio.h>
53
54 #include <asm/system.h>
55 #include <asm/uaccess.h>
56
57 #include <linux/fs.h>
58 #include <linux/file.h>
59 #include <linux/stat.h>
60 #include <linux/list.h>
61 #include <linux/sysctl.h>
62 #include <asm/segment.h>
63
64 #define DEBUG_SUBSYSTEM S_LND
65
66 #include <libcfs/kp30.h>
67 #include <lnet/lnet.h>
68 #include <lnet/lib-lnet.h>
69
70 /* fixed constants */
71 #define KQSW_SMALLMSG                  (4<<10)  /* small/large ep receiver breakpoint */
72 #define KQSW_RESCHED                    100     /* # busy loops that forces scheduler to yield */
73
74 #define KQSW_CKSUM                      0       /* enable checksumming (protocol incompatible) */
75
76 /*
77  * derived constants
78  */
79
80 #define KQSW_TX_BUFFER_SIZE     (offsetof(kqswnal_msg_t, \
81                                           kqm_u.immediate.kqim_payload[*kqswnal_tunables.kqn_tx_maxcontig]))
82 /* The pre-allocated tx buffer (hdr + small payload) */
83
84 #define KQSW_NTXMSGPAGES        (btopr(KQSW_TX_BUFFER_SIZE) + 1 + btopr(LNET_MAX_PAYLOAD) + 1)
85 /* Reserve elan address space for pre-allocated and pre-mapped transmit
86  * buffer and a full payload too.  Extra pages allow for page alignment */
87
88 #define KQSW_NRXMSGPAGES_SMALL  (btopr(KQSW_SMALLMSG))
89 /* receive hdr/payload always contiguous and page aligned */
90 #define KQSW_NRXMSGBYTES_SMALL  (KQSW_NRXMSGPAGES_SMALL * PAGE_SIZE)
91
92 #define KQSW_NRXMSGPAGES_LARGE  (btopr(sizeof(lnet_msg_t) + LNET_MAX_PAYLOAD))
93 /* receive hdr/payload always contiguous and page aligned */
94 #define KQSW_NRXMSGBYTES_LARGE  (KQSW_NRXMSGPAGES_LARGE * PAGE_SIZE)
95 /* biggest complete packet we can receive (or transmit) */
96
97 /* Wire messages */
98 /* Remote memory descriptor */
99 typedef struct
100 {
101         __u32            kqrmd_nfrag;           /* # frags */
102         EP_NMD           kqrmd_frag[0];         /* actual frags */
103 } kqswnal_remotemd_t;
104
105 /* Immediate data */
106 typedef struct
107 {
108         lnet_hdr_t       kqim_hdr;              /* LNET header */
109         char             kqim_payload[0];       /* piggy-backed payload */
110 } WIRE_ATTR kqswnal_immediate_msg_t;
111
112 /* RDMA request */
113 typedef struct
114 {
115         lnet_hdr_t          kqrm_hdr;           /* LNET header */
116         kqswnal_remotemd_t  kqrm_rmd;           /* peer's buffer */
117 } WIRE_ATTR kqswnal_rdma_msg_t;
118
119 typedef struct
120 {
121         __u32            kqm_magic;             /* I'm a qswlnd message */
122         __u16            kqm_version;           /* this is my version number */
123         __u16            kqm_type;              /* msg type */
124 #if KQSW_CKSUM
125         __u32            kqm_cksum;             /* crc32 checksum */
126         __u32            kqm_nob;               /* original msg length */
127 #endif
128         union {
129                 kqswnal_immediate_msg_t  immediate;
130                 kqswnal_rdma_msg_t       rdma;
131         } WIRE_ATTR kqm_u;
132 } WIRE_ATTR kqswnal_msg_t;
133
134 #if KQSW_CKSUM                                           /* enable checksums ? */
135 # include <linux/crc32.h>
136 static inline __u32 kqswnal_csum(__u32 crc, unsigned char const *p, size_t len)
137 {
138 #if 1
139         return crc32_le(crc, p, len);
140 #else
141         while (len-- > 0)
142                 crc = ((crc + 0x100) & ~0xff) | ((crc + *p++) & 0xff) ;
143         return crc;
144 #endif
145 }
146 # define QSWLND_PROTO_VERSION         0xbeef
147 #else
148 # define QSWLND_PROTO_VERSION         1
149 #endif
150
151 #define QSWLND_MSG_IMMEDIATE          0
152 #define QSWLND_MSG_RDMA               1
153
154 typedef union {
155         EP_STATUSBLK     ep_statusblk;
156         struct {
157                 __u32       status;
158                 __u32       magic;
159                 __u32       version;
160                 union {
161                         struct {
162                                 __u32    len;
163                                 __u32    cksum;
164                         } WIRE_ATTR get;
165                 } WIRE_ATTR u;
166         } WIRE_ATTR     msg;
167 } kqswnal_rpc_reply_t;
168
169 typedef struct kqswnal_rx
170 {
171         struct list_head krx_list;              /* enqueue -> thread */
172         struct kqswnal_rx *krx_alloclist;       /* stack in kqn_rxds */
173         EP_RCVR         *krx_eprx;              /* port to post receives to */
174         EP_RXD          *krx_rxd;               /* receive descriptor (for repost) */
175         EP_NMD           krx_elanbuffer;        /* contiguous Elan buffer */
176         int              krx_npages;            /* # pages in receive buffer */
177         int              krx_nob;               /* Number Of Bytes received into buffer */
178         int              krx_rpc_reply_needed:1; /* peer waiting for EKC RPC reply */
179         int              krx_raw_lnet_hdr:1;    /* msg is a raw lnet hdr (portals compatible) */
180         int              krx_state;             /* what this RX is doing */
181         atomic_t         krx_refcount;          /* how to tell when rpc is done */
182 #if KQSW_CKSUM
183         __u32            krx_cksum;             /* checksum */
184 #endif
185         kqswnal_rpc_reply_t krx_rpc_reply;      /* rpc reply status block */
186         lnet_kiov_t      krx_kiov[KQSW_NRXMSGPAGES_LARGE]; /* buffer frags */
187 }  kqswnal_rx_t;
188
189 #define KRX_POSTED       1                      /* receiving */
190 #define KRX_PARSE        2                      /* ready to be parsed */
191 #define KRX_COMPLETING   3                      /* waiting to be completed */
192
193
194 typedef struct kqswnal_tx
195 {
196         struct list_head  ktx_list;             /* enqueue idle/active */
197         struct list_head  ktx_schedlist;        /* enqueue on scheduler */
198         struct kqswnal_tx *ktx_alloclist;       /* stack in kqn_txds */
199         unsigned int      ktx_state:7;          /* What I'm doing */
200         unsigned int      ktx_firsttmpfrag:1;   /* ktx_frags[0] is in my ebuffer ? 0 : 1 */
201         __u32             ktx_basepage;         /* page offset in reserved elan tx vaddrs for mapping pages */
202         int               ktx_npages;           /* pages reserved for mapping messages */
203         int               ktx_nmappedpages;     /* # pages mapped for current message */
204         int               ktx_port;             /* destination ep port */
205         lnet_nid_t        ktx_nid;              /* destination node */
206         void             *ktx_args[3];          /* completion passthru */
207         char             *ktx_buffer;           /* pre-allocated contiguous buffer for hdr + small payloads */
208         unsigned long     ktx_launchtime;       /* when (in jiffies) the transmit was launched */
209         int               ktx_status;           /* completion status */
210 #if KQSW_CKSUM
211         __u32             ktx_cksum;            /* optimized GET payload checksum */
212 #endif
213         /* debug/info fields */
214         pid_t             ktx_launcher;         /* pid of launching process */
215
216         int               ktx_nfrag;            /* # message frags */
217         int               ktx_rail;             /* preferred rail */
218         EP_NMD            ktx_ebuffer;          /* elan mapping of ktx_buffer */
219         EP_NMD            ktx_frags[EP_MAXFRAG];/* elan mapping of msg frags */
220 } kqswnal_tx_t;
221
222 #define KTX_IDLE        0                       /* on kqn_idletxds */
223 #define KTX_SENDING     1                       /* normal send */
224 #define KTX_GETTING     2                       /* sending optimised get */
225 #define KTX_PUTTING     3                       /* sending optimised put */
226 #define KTX_RDMA_FETCH  4                       /* handling optimised put */
227 #define KTX_RDMA_STORE  5                       /* handling optimised get */
228
229 typedef struct
230 {
231         int               *kqn_tx_maxcontig;    /* maximum payload to defrag */
232         int               *kqn_ntxmsgs;         /* # normal tx msgs */
233         int               *kqn_credits;         /* # concurrent sends */
234         int               *kqn_peercredits;     /* # concurrent sends to 1 peer */
235         int               *kqn_nrxmsgs_large;   /* # 'large' rx msgs */
236         int               *kqn_ep_envelopes_large; /* # 'large' rx ep envelopes */
237         int               *kqn_nrxmsgs_small;   /* # 'small' rx msgs */
238         int               *kqn_ep_envelopes_small; /* # 'small' rx ep envelopes */
239         int               *kqn_optimized_puts;  /* optimized PUTs? */
240         int               *kqn_optimized_gets;  /* optimized GETs? */
241 #if KQSW_CKSUM
242         int               *kqn_inject_csum_error; /* # csum errors to inject */
243 #endif
244
245 #if defined(CONFIG_SYSCTL) && !CFS_SYSFS_MODULE_PARM
246         cfs_sysctl_table_header_t *kqn_sysctl;  /* sysctl interface */
247 #endif
248 } kqswnal_tunables_t;
249
250 typedef struct
251 {
252         char               kqn_init;            /* what's been initialised */
253         char               kqn_shuttingdown;    /* I'm trying to shut down */
254         atomic_t           kqn_nthreads;        /* # threads running */
255         lnet_ni_t         *kqn_ni;              /* _the_ instance of me */
256
257         kqswnal_rx_t      *kqn_rxds;            /* stack of all the receive descriptors */
258         kqswnal_tx_t      *kqn_txds;            /* stack of all the transmit descriptors */
259
260         struct list_head   kqn_idletxds;        /* transmit descriptors free to use */
261         struct list_head   kqn_activetxds;      /* transmit descriptors being used */
262         spinlock_t         kqn_idletxd_lock;    /* serialise idle txd access */
263         atomic_t           kqn_pending_txs;     /* # transmits being prepped */
264
265         spinlock_t         kqn_sched_lock;      /* serialise packet schedulers */
266         wait_queue_head_t  kqn_sched_waitq;     /* scheduler blocks here */
267
268         struct list_head   kqn_readyrxds;       /* rxds full of data */
269         struct list_head   kqn_donetxds;        /* completed transmits */
270         struct list_head   kqn_delayedtxds;     /* delayed transmits */
271
272         EP_SYS            *kqn_ep;              /* elan system */
273         EP_NMH            *kqn_ep_tx_nmh;       /* elan reserved tx vaddrs */
274         EP_NMH            *kqn_ep_rx_nmh;       /* elan reserved rx vaddrs */
275         EP_XMTR           *kqn_eptx;            /* elan transmitter */
276         EP_RCVR           *kqn_eprx_small;      /* elan receiver (small messages) */
277         EP_RCVR           *kqn_eprx_large;      /* elan receiver (large messages) */
278
279         int                kqn_nnodes;          /* this cluster's size */
280         int                kqn_elanid;          /* this nodes's elan ID */
281
282         EP_STATUSBLK       kqn_rpc_success;     /* preset RPC reply status blocks */
283         EP_STATUSBLK       kqn_rpc_failed;
284         EP_STATUSBLK       kqn_rpc_version;     /* reply to future version query */
285         EP_STATUSBLK       kqn_rpc_magic;       /* reply to future version query */
286 }  kqswnal_data_t;
287
288 /* kqn_init state */
289 #define KQN_INIT_NOTHING        0               /* MUST BE ZERO so zeroed state is initialised OK */
290 #define KQN_INIT_DATA           1
291 #define KQN_INIT_ALL            2
292
293 extern kqswnal_tunables_t  kqswnal_tunables;
294 extern kqswnal_data_t      kqswnal_data;
295
296 extern int kqswnal_thread_start (int (*fn)(void *arg), void *arg);
297 extern void kqswnal_rxhandler(EP_RXD *rxd);
298 extern int kqswnal_scheduler (void *);
299 extern void kqswnal_rx_done (kqswnal_rx_t *krx);
300
301 static inline lnet_nid_t
302 kqswnal_elanid2nid (int elanid)
303 {
304         return LNET_MKNID(LNET_NIDNET(kqswnal_data.kqn_ni->ni_nid), elanid);
305 }
306
307 static inline int
308 kqswnal_nid2elanid (lnet_nid_t nid)
309 {
310         __u32 elanid = LNET_NIDADDR(nid);
311
312         /* not in this cluster? */
313         return (elanid >= kqswnal_data.kqn_nnodes) ? -1 : elanid;
314 }
315
316 static inline lnet_nid_t
317 kqswnal_rx_nid(kqswnal_rx_t *krx)
318 {
319         return (kqswnal_elanid2nid(ep_rxd_node(krx->krx_rxd)));
320 }
321
322 static inline int
323 kqswnal_pages_spanned (void *base, int nob)
324 {
325         unsigned long first_page = ((unsigned long)base) >> PAGE_SHIFT;
326         unsigned long last_page  = (((unsigned long)base) + (nob - 1)) >> PAGE_SHIFT;
327
328         LASSERT (last_page >= first_page);      /* can't wrap address space */
329         return (last_page - first_page + 1);
330 }
331
332 static inline void kqswnal_rx_decref (kqswnal_rx_t *krx)
333 {
334         LASSERT (atomic_read (&krx->krx_refcount) > 0);
335         if (atomic_dec_and_test (&krx->krx_refcount))
336                 kqswnal_rx_done(krx);
337 }
338
339 int kqswnal_startup (lnet_ni_t *ni);
340 void kqswnal_shutdown (lnet_ni_t *ni);
341 int kqswnal_ctl (lnet_ni_t *ni, unsigned int cmd, void *arg);
342 int kqswnal_send (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg);
343 int kqswnal_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, 
344                  int delayed, unsigned int niov, 
345                  struct iovec *iov, lnet_kiov_t *kiov,
346                  unsigned int offset, unsigned int mlen, unsigned int rlen);
347
348 int kqswnal_tunables_init(void);
349 void kqswnal_tunables_fini(void);
350
351 #endif /* _QSWNAL_H */