Whamcloud - gitweb
* lctl set_route <nid> <up/down> enables or disables particular portals
[fs/lustre-release.git] / lustre / portals / knals / qswnal / qswnal.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 #define EXPORT_SYMTAB
28
29 #ifdef PROPRIETARY_ELAN
30 # include <qsw/kernel.h>
31 #else
32 # include <qsnet/kernel.h>
33 #endif
34
35 #undef printf                                   /* nasty QSW #define */
36
37 #include <linux/config.h>
38 #include <linux/module.h>
39
40 #include <elan3/elanregs.h>
41 #include <elan3/elandev.h>
42 #include <elan3/elanvp.h>
43 #include <elan3/elan3mmu.h>
44 #include <elan3/elanctxt.h>
45 #include <elan3/elandebug.h>
46 #include <elan3/urom_addrs.h>
47 #include <elan3/busops.h>
48 #include <elan3/kcomm.h>
49
50 #include <linux/kernel.h>
51 #include <linux/mm.h>
52 #include <linux/string.h>
53 #include <linux/stat.h>
54 #include <linux/errno.h>
55 #include <linux/locks.h>
56 #include <linux/unistd.h>
57 #include <net/sock.h>
58 #include <linux/uio.h>
59
60 #include <asm/system.h>
61 #include <asm/uaccess.h>
62
63 #include <linux/fs.h>
64 #include <linux/file.h>
65 #include <linux/stat.h>
66 #include <linux/list.h>
67 #include <asm/uaccess.h>
68 #include <asm/segment.h>
69
70 #define DEBUG_SUBSYSTEM S_QSWNAL
71
72 #include <linux/kp30.h>
73 #include <portals/p30.h>
74 #include <portals/lib-p30.h>
75
76 #define KQSW_CHECKSUM   0
77 #if KQSW_CHECKSUM
78 typedef unsigned long kqsw_csum_t;
79 #define KQSW_CSUM_SIZE  (2 * sizeof (kqsw_csum_t))
80 #else
81 #define KQSW_CSUM_SIZE  0
82 #endif
83 #define KQSW_HDR_SIZE   (sizeof (ptl_hdr_t) + KQSW_CSUM_SIZE)
84
85 /*
86  *  Elan NAL
87  */
88 #define EP_SVC_LARGE_PORTALS_SMALL      (0x10)  /* Portals over elan port number (large payloads) */
89 #define EP_SVC_LARGE_PORTALS_LARGE      (0x11)  /* Portals over elan port number (small payloads) */
90 /* NB small/large message sizes are GLOBAL constants */
91
92 /*
93  * Performance Tuning defines
94  * NB no mention of PAGE_SIZE for interoperability
95  */
96 #if PTL_LARGE_MTU
97 # define KQSW_MAXPAYLOAD                (256<<10) /* biggest message this NAL will cope with */
98 #else
99 # define KQSW_MAXPAYLOAD                (64<<10) /* biggest message this NAL will cope with */
100 #endif
101
102 #define KQSW_SMALLPAYLOAD               ((4<<10) - KQSW_HDR_SIZE) /* small/large ep receiver breakpoint */
103
104 #define KQSW_TX_MAXCONTIG               (1<<10) /* largest payload that gets made contiguous on transmit */
105
106 #define KQSW_NTXMSGS                    8       /* # normal transmit messages */
107 #define KQSW_NNBLK_TXMSGS               256     /* # reserved transmit messages if can't block */
108
109 #define KQSW_NRXMSGS_LARGE              64      /* # large receive buffers */
110 #define KQSW_EP_ENVELOPES_LARGE         128     /* # large ep envelopes */
111
112 #define KQSW_NRXMSGS_SMALL              256     /* # small receive buffers */
113 #define KQSW_EP_ENVELOPES_SMALL         2048    /* # small ep envelopes */
114
115 #define KQSW_RESCHED                    100     /* # busy loops that forces scheduler to yield */
116
117 /*
118  * derived constants
119  */
120
121 #define KQSW_TX_BUFFER_SIZE     (KQSW_HDR_SIZE + KQSW_TX_MAXCONTIG)
122 /* The pre-allocated tx buffer (hdr + small payload) */
123
124 #define KQSW_NTXMSGPAGES        (btopr(KQSW_TX_BUFFER_SIZE) + 1 + btopr(KQSW_MAXPAYLOAD) + 1)
125 /* Reserve elan address space for pre-allocated and pre-mapped transmit
126  * buffer and a full payload too.  Extra pages allow for page alignment */
127
128 #define KQSW_NRXMSGPAGES_SMALL  (btopr(KQSW_HDR_SIZE + KQSW_SMALLPAYLOAD))
129 /* receive hdr/payload always contiguous and page aligned */
130 #define KQSW_NRXMSGBYTES_SMALL  (KQSW_NRXMSGPAGES_SMALL * PAGE_SIZE)
131
132 #define KQSW_NRXMSGPAGES_LARGE  (btopr(KQSW_HDR_SIZE + KQSW_MAXPAYLOAD))
133 /* receive hdr/payload always contiguous and page aligned */
134 #define KQSW_NRXMSGBYTES_LARGE  (KQSW_NRXMSGPAGES_LARGE * PAGE_SIZE)
135 /* biggest complete packet we can receive (or transmit) */
136
137
138 typedef struct 
139 {
140         struct list_head krx_list;              /* enqueue -> thread */
141         EP_RCVR         *krx_eprx;              /* port to post receives to */
142         EP_RXD          *krx_rxd;               /* receive descriptor (for repost) */
143         E3_Addr          krx_elanaddr;          /* Elan address of buffer (contiguous in elan vm) */
144         int              krx_npages;            /* # pages in receive buffer */
145         int              krx_nob;               /* Number Of Bytes received into buffer */
146         kpr_fwd_desc_t   krx_fwd;               /* embedded forwarding descriptor */
147         struct page     *krx_pages[KQSW_NRXMSGPAGES_LARGE]; /* pages allocated */
148         struct iovec     krx_iov[KQSW_NRXMSGPAGES_LARGE]; /* iovec for forwarding */
149 }  kqswnal_rx_t;
150
151 typedef struct
152 {
153         struct list_head  ktx_list;             /* enqueue idle/active */
154         struct list_head  ktx_delayed_list;     /* enqueue delayedtxds */
155         int               ktx_isnblk:1;         /* reserved descriptor? */
156         int               ktx_forwarding:1;     /* forwarding (rather than local send) */
157         uint32_t          ktx_basepage;         /* page offset in reserved elan tx vaddrs for mapping pages */
158         int               ktx_npages;           /* pages reserved for mapping messages */
159         int               ktx_nmappedpages;     /* # pages mapped for current message */
160         EP_IOVEC          ktx_iov[EP_MAXFRAG];  /* msg frags (elan vaddrs) */
161         int               ktx_niov;             /* # message frags */
162         int               ktx_port;             /* destination ep port */
163         ptl_nid_t         ktx_nid;              /* destination node */
164         void             *ktx_args[2];          /* completion passthru */
165         E3_Addr           ktx_ebuffer;          /* elan address of ktx_buffer */
166         char             *ktx_buffer;           /* pre-allocated contiguous buffer for hdr + small payloads */
167         unsigned long     ktx_launchtime;       /* when (in jiffies) the transmit was launched */
168
169         /* debug/info fields */
170         pid_t             ktx_launcher;         /* pid of launching process */
171         ptl_hdr_t        *ktx_wire_hdr;         /* portals header (wire endian) */
172 } kqswnal_tx_t;
173
174 typedef struct
175 {
176         char               kqn_init;            /* what's been initialised */
177         char               kqn_shuttingdown;    /* I'm trying to shut down */
178         atomic_t           kqn_nthreads;        /* # threads still running */
179
180         kqswnal_rx_t      *kqn_rxds;            /* all the receive descriptors */
181         kqswnal_tx_t      *kqn_txds;            /* all the transmit descriptors */
182
183         struct list_head   kqn_idletxds;        /* transmit descriptors free to use */
184         struct list_head   kqn_nblk_idletxds;   /* reserved free transmit descriptors */
185         struct list_head   kqn_activetxds;      /* transmit descriptors being used */
186         spinlock_t         kqn_idletxd_lock;    /* serialise idle txd access */
187         wait_queue_head_t  kqn_idletxd_waitq;   /* sender blocks here waiting for idle txd */
188         struct list_head   kqn_idletxd_fwdq;    /* forwarded packets block here waiting for idle txd */
189         
190         spinlock_t         kqn_sched_lock;      /* serialise packet schedulers */
191         wait_queue_head_t  kqn_sched_waitq;     /* scheduler blocks here */
192
193         struct list_head   kqn_readyrxds;       /* rxds full of data */
194         struct list_head   kqn_delayedfwds;     /* delayed forwards */
195         struct list_head   kqn_delayedtxds;     /* delayed transmits */
196
197         spinlock_t         kqn_statelock;       /* cb_cli/cb_sti */
198         nal_cb_t          *kqn_cb;              /* -> kqswnal_lib */
199         EP_DEV            *kqn_epdev;           /* elan device */
200         EP_XMTR           *kqn_eptx;            /* elan transmitter */
201         EP_RCVR           *kqn_eprx_small;      /* elan receiver (small messages) */
202         EP_RCVR           *kqn_eprx_large;      /* elan receiver (large messages) */
203         ELAN3_DMA_HANDLE  *kqn_eptxdmahandle;   /* elan reserved tx vaddrs */
204         ELAN3_DMA_HANDLE  *kqn_eprxdmahandle;   /* elan reserved rx vaddrs */
205         kpr_router_t       kqn_router;          /* connection to Kernel Portals Router module */
206
207         ptl_nid_t          kqn_nid_offset;      /* this cluster's NID offset */
208         int                kqn_nnodes;          /* this cluster's size */
209         int                kqn_elanid;          /* this nodes's elan ID */
210 }  kqswnal_data_t;
211
212 /* kqn_init state */
213 #define KQN_INIT_NOTHING        0               /* MUST BE ZERO so zeroed state is initialised OK */
214 #define KQN_INIT_DATA           1
215 #define KQN_INIT_PTL            2
216 #define KQN_INIT_ALL            3
217
218 extern nal_cb_t        kqswnal_lib;
219 extern nal_t           kqswnal_api;
220 extern kqswnal_data_t  kqswnal_data;
221
222 extern int kqswnal_thread_start (int (*fn)(void *arg), void *arg);
223 extern void kqswnal_rxhandler(EP_RXD *rxd);
224 extern int kqswnal_scheduler (void *);
225 extern void kqswnal_fwd_packet (void *arg, kpr_fwd_desc_t *fwd);
226
227 static inline ptl_nid_t
228 kqswnal_elanid2nid (int elanid) 
229 {
230         return (kqswnal_data.kqn_nid_offset + elanid);
231 }
232
233 static inline int
234 kqswnal_nid2elanid (ptl_nid_t nid) 
235 {
236         /* not in this cluster? */
237         if (nid < kqswnal_data.kqn_nid_offset ||
238             nid >= kqswnal_data.kqn_nid_offset + kqswnal_data.kqn_nnodes)
239                 return (-1);
240         
241         return (nid - kqswnal_data.kqn_nid_offset);
242 }
243
244 static inline void
245 kqswnal_requeue_rx (kqswnal_rx_t *krx)
246 {
247         ep_requeue_receive (krx->krx_rxd, kqswnal_rxhandler, krx,
248                             krx->krx_elanaddr, krx->krx_npages * PAGE_SIZE);
249 }
250
251 static inline int
252 kqswnal_pages_spanned (void *base, int nob)
253 {
254         unsigned long first_page = ((unsigned long)base) >> PAGE_SHIFT;
255         unsigned long last_page  = (((unsigned long)base) + (nob - 1)) >> PAGE_SHIFT;
256
257         LASSERT (last_page >= first_page);      /* can't wrap address space */
258         return (last_page - first_page + 1);
259 }
260
261 #if KQSW_CHECKSUM
262 static inline kqsw_csum_t kqsw_csum (kqsw_csum_t sum, void *base, int nob)
263 {
264         unsigned char *ptr = (unsigned char *)base;
265         
266         while (nob-- > 0)
267                 sum += *ptr++;
268         
269         return (sum);
270 }
271 #endif
272
273 #endif /* _QSWNAL_H */