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