Whamcloud - gitweb
Mass conversion of all copyright messages to Oracle.
[fs/lustre-release.git] / lnet / ulnds / ptllnd / ptllnd.c
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) 2007, 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/ulnds/ptllnd/ptllnd.c
37  *
38  * Author: Eric Barton <eeb@bartonsoftware.com>
39  */
40
41 #include "ptllnd.h"
42
43 lnd_t               the_ptllnd = {
44         .lnd_type       = PTLLND,
45         .lnd_startup    = ptllnd_startup,
46         .lnd_shutdown   = ptllnd_shutdown,
47         .lnd_ctl        = ptllnd_ctl,
48         .lnd_send       = ptllnd_send,
49         .lnd_recv       = ptllnd_recv,
50         .lnd_eager_recv = ptllnd_eager_recv,
51         .lnd_wait       = ptllnd_wait,
52         .lnd_setasync   = ptllnd_setasync,
53 };
54
55 static int ptllnd_ni_count = 0;
56
57 static cfs_list_t ptllnd_idle_history;
58 static cfs_list_t ptllnd_history_list;
59
60 void
61 ptllnd_history_fini(void)
62 {
63         ptllnd_he_t *he;
64
65         while (!cfs_list_empty(&ptllnd_idle_history)) {
66                 he = cfs_list_entry(ptllnd_idle_history.next,
67                                     ptllnd_he_t, he_list);
68
69                 cfs_list_del(&he->he_list);
70                 LIBCFS_FREE(he, sizeof(*he));
71         }
72
73         while (!cfs_list_empty(&ptllnd_history_list)) {
74                 he = cfs_list_entry(ptllnd_history_list.next,
75                                     ptllnd_he_t, he_list);
76
77                 cfs_list_del(&he->he_list);
78                 LIBCFS_FREE(he, sizeof(*he));
79         }
80 }
81
82 int
83 ptllnd_history_init(void)
84 {
85         int          i;
86         ptllnd_he_t *he;
87         int          n;
88         int          rc;
89
90         CFS_INIT_LIST_HEAD(&ptllnd_idle_history);
91         CFS_INIT_LIST_HEAD(&ptllnd_history_list);
92
93         rc = ptllnd_parse_int_tunable(&n, "PTLLND_HISTORY", 0);
94         if (rc != 0)
95                 return rc;
96
97         for (i = 0; i < n; i++) {
98                 LIBCFS_ALLOC(he, sizeof(*he));
99                 if (he == NULL) {
100                         ptllnd_history_fini();
101                         return -ENOMEM;
102                 }
103
104                 cfs_list_add(&he->he_list, &ptllnd_idle_history);
105         }
106
107         PTLLND_HISTORY("Init");
108
109         return 0;
110 }
111
112 void
113 ptllnd_history(const char *fn, const char *file, const int line,
114                const char *fmt, ...)
115 {
116         static int     seq;
117
118         va_list        ap;
119         ptllnd_he_t   *he;
120
121         if (!cfs_list_empty(&ptllnd_idle_history)) {
122                 he = cfs_list_entry(ptllnd_idle_history.next,
123                                     ptllnd_he_t, he_list);
124         } else if (!cfs_list_empty(&ptllnd_history_list)) {
125                 he = cfs_list_entry(ptllnd_history_list.next,
126                                     ptllnd_he_t, he_list);
127         } else {
128                 return;
129         }
130
131         cfs_list_del(&he->he_list);
132         cfs_list_add_tail(&he->he_list, &ptllnd_history_list);
133
134         he->he_seq = seq++;
135         he->he_fn = fn;
136         he->he_file = file;
137         he->he_line = line;
138         gettimeofday(&he->he_time, NULL);
139
140         va_start(ap, fmt);
141         vsnprintf(he->he_msg, sizeof(he->he_msg), fmt, ap);
142         va_end(ap);
143 }
144
145 void
146 ptllnd_dump_history(void)
147 {
148         ptllnd_he_t    *he;
149
150         PTLLND_HISTORY("dumping...");
151
152         while (!cfs_list_empty(&ptllnd_history_list)) {
153                 he = cfs_list_entry(ptllnd_history_list.next,
154                                 ptllnd_he_t, he_list);
155
156                 cfs_list_del(&he->he_list);
157
158                 CDEBUG(D_WARNING, "%d %d.%06d (%s:%d:%s()) %s\n", he->he_seq,
159                        (int)he->he_time.tv_sec, (int)he->he_time.tv_usec,
160                        he->he_file, he->he_line, he->he_fn, he->he_msg);
161
162                 cfs_list_add_tail(&he->he_list, &ptllnd_idle_history);
163         }
164
165         PTLLND_HISTORY("complete");
166 }
167
168 void
169 ptllnd_assert_wire_constants (void)
170 {
171         /* Wire protocol assertions generated by 'wirecheck'
172          * running on Linux fedora 2.6.11-co-0.6.4 #1 Mon Jun 19 05:36:13 UTC 2006 i686 i686 i386 GNU
173          * with gcc version 4.1.1 20060525 (Red Hat 4.1.1-1) */
174
175
176         /* Constants... */
177         CLASSERT (PTL_RESERVED_MATCHBITS == 0x100);
178         CLASSERT (LNET_MSG_MATCHBITS == 0);
179         CLASSERT (PTLLND_MSG_MAGIC == 0x50746C4E);
180         CLASSERT (PTLLND_MSG_VERSION == 0x04);
181         CLASSERT (PTLLND_RDMA_OK == 0x00);
182         CLASSERT (PTLLND_RDMA_FAIL == 0x01);
183         CLASSERT (PTLLND_MSG_TYPE_INVALID == 0x00);
184         CLASSERT (PTLLND_MSG_TYPE_PUT == 0x01);
185         CLASSERT (PTLLND_MSG_TYPE_GET == 0x02);
186         CLASSERT (PTLLND_MSG_TYPE_IMMEDIATE == 0x03);
187         CLASSERT (PTLLND_MSG_TYPE_NOOP == 0x04);
188         CLASSERT (PTLLND_MSG_TYPE_HELLO == 0x05);
189         CLASSERT (PTLLND_MSG_TYPE_NAK == 0x06);
190
191         /* Checks for struct kptl_msg_t */
192         CLASSERT ((int)sizeof(kptl_msg_t) == 136);
193         CLASSERT ((int)offsetof(kptl_msg_t, ptlm_magic) == 0);
194         CLASSERT ((int)sizeof(((kptl_msg_t *)0)->ptlm_magic) == 4);
195         CLASSERT ((int)offsetof(kptl_msg_t, ptlm_version) == 4);
196         CLASSERT ((int)sizeof(((kptl_msg_t *)0)->ptlm_version) == 2);
197         CLASSERT ((int)offsetof(kptl_msg_t, ptlm_type) == 6);
198         CLASSERT ((int)sizeof(((kptl_msg_t *)0)->ptlm_type) == 1);
199         CLASSERT ((int)offsetof(kptl_msg_t, ptlm_credits) == 7);
200         CLASSERT ((int)sizeof(((kptl_msg_t *)0)->ptlm_credits) == 1);
201         CLASSERT ((int)offsetof(kptl_msg_t, ptlm_nob) == 8);
202         CLASSERT ((int)sizeof(((kptl_msg_t *)0)->ptlm_nob) == 4);
203         CLASSERT ((int)offsetof(kptl_msg_t, ptlm_cksum) == 12);
204         CLASSERT ((int)sizeof(((kptl_msg_t *)0)->ptlm_cksum) == 4);
205         CLASSERT ((int)offsetof(kptl_msg_t, ptlm_srcnid) == 16);
206         CLASSERT ((int)sizeof(((kptl_msg_t *)0)->ptlm_srcnid) == 8);
207         CLASSERT ((int)offsetof(kptl_msg_t, ptlm_srcstamp) == 24);
208         CLASSERT ((int)sizeof(((kptl_msg_t *)0)->ptlm_srcstamp) == 8);
209         CLASSERT ((int)offsetof(kptl_msg_t, ptlm_dstnid) == 32);
210         CLASSERT ((int)sizeof(((kptl_msg_t *)0)->ptlm_dstnid) == 8);
211         CLASSERT ((int)offsetof(kptl_msg_t, ptlm_dststamp) == 40);
212         CLASSERT ((int)sizeof(((kptl_msg_t *)0)->ptlm_dststamp) == 8);
213         CLASSERT ((int)offsetof(kptl_msg_t, ptlm_srcpid) == 48);
214         CLASSERT ((int)sizeof(((kptl_msg_t *)0)->ptlm_srcpid) == 4);
215         CLASSERT ((int)offsetof(kptl_msg_t, ptlm_dstpid) == 52);
216         CLASSERT ((int)sizeof(((kptl_msg_t *)0)->ptlm_dstpid) == 4);
217         CLASSERT ((int)offsetof(kptl_msg_t, ptlm_u.immediate) == 56);
218         CLASSERT ((int)sizeof(((kptl_msg_t *)0)->ptlm_u.immediate) == 72);
219         CLASSERT ((int)offsetof(kptl_msg_t, ptlm_u.rdma) == 56);
220         CLASSERT ((int)sizeof(((kptl_msg_t *)0)->ptlm_u.rdma) == 80);
221         CLASSERT ((int)offsetof(kptl_msg_t, ptlm_u.hello) == 56);
222         CLASSERT ((int)sizeof(((kptl_msg_t *)0)->ptlm_u.hello) == 12);
223
224         /* Checks for struct kptl_immediate_msg_t */
225         CLASSERT ((int)sizeof(kptl_immediate_msg_t) == 72);
226         CLASSERT ((int)offsetof(kptl_immediate_msg_t, kptlim_hdr) == 0);
227         CLASSERT ((int)sizeof(((kptl_immediate_msg_t *)0)->kptlim_hdr) == 72);
228         CLASSERT ((int)offsetof(kptl_immediate_msg_t, kptlim_payload[13]) == 85);
229         CLASSERT ((int)sizeof(((kptl_immediate_msg_t *)0)->kptlim_payload[13]) == 1);
230
231         /* Checks for struct kptl_rdma_msg_t */
232         CLASSERT ((int)sizeof(kptl_rdma_msg_t) == 80);
233         CLASSERT ((int)offsetof(kptl_rdma_msg_t, kptlrm_hdr) == 0);
234         CLASSERT ((int)sizeof(((kptl_rdma_msg_t *)0)->kptlrm_hdr) == 72);
235         CLASSERT ((int)offsetof(kptl_rdma_msg_t, kptlrm_matchbits) == 72);
236         CLASSERT ((int)sizeof(((kptl_rdma_msg_t *)0)->kptlrm_matchbits) == 8);
237
238         /* Checks for struct kptl_hello_msg_t */
239         CLASSERT ((int)sizeof(kptl_hello_msg_t) == 12);
240         CLASSERT ((int)offsetof(kptl_hello_msg_t, kptlhm_matchbits) == 0);
241         CLASSERT ((int)sizeof(((kptl_hello_msg_t *)0)->kptlhm_matchbits) == 8);
242         CLASSERT ((int)offsetof(kptl_hello_msg_t, kptlhm_max_msg_size) == 8);
243         CLASSERT ((int)sizeof(((kptl_hello_msg_t *)0)->kptlhm_max_msg_size) == 4);
244 }
245
246 int
247 ptllnd_parse_int_tunable(int *value, char *name, int dflt)
248 {
249         char    *env = getenv(name);
250         char    *end;
251
252         if (env == NULL) {
253                 *value = dflt;
254                 return 0;
255         }
256
257         *value = strtoull(env, &end, 0);
258         if (*end == 0)
259                 return 0;
260
261         CERROR("Can't parse tunable %s=%s\n", name, env);
262         return -EINVAL;
263 }
264
265 int
266 ptllnd_get_tunables(lnet_ni_t *ni)
267 {
268         ptllnd_ni_t *plni = ni->ni_data;
269         int          max_msg_size;
270         int          msgs_per_buffer;
271         int          rc;
272         int          temp;
273
274         /*  Other tunable defaults depend on this */
275         rc = ptllnd_parse_int_tunable(&plni->plni_debug, "PTLLND_DEBUG", 0);
276         if (rc != 0)
277                 return rc;
278
279         rc = ptllnd_parse_int_tunable(&plni->plni_portal,
280                                       "PTLLND_PORTAL", PTLLND_PORTAL);
281         if (rc != 0)
282                 return rc;
283
284         rc = ptllnd_parse_int_tunable(&temp,
285                                       "PTLLND_PID", PTLLND_PID);
286         if (rc != 0)
287                 return rc;
288         plni->plni_ptllnd_pid = (ptl_pid_t)temp;
289
290         rc = ptllnd_parse_int_tunable(&plni->plni_peer_credits,
291                                       "PTLLND_PEERCREDITS", PTLLND_PEERCREDITS);
292         if (rc != 0)
293                 return rc;
294         if (plni->plni_peer_credits > PTLLND_MSG_MAX_CREDITS) {
295                 CERROR("PTLLND_PEERCREDITS must be <= %d\n", PTLLND_MSG_MAX_CREDITS);
296                 return -EINVAL;
297         }
298
299         rc = ptllnd_parse_int_tunable(&max_msg_size,
300                                       "PTLLND_MAX_MSG_SIZE",
301                                       PTLLND_MAX_ULND_MSG_SIZE);
302         if (rc != 0)
303                 return rc;
304
305         rc = ptllnd_parse_int_tunable(&msgs_per_buffer,
306                                       "PTLLND_MSGS_PER_BUFFER", 64);
307         if (rc != 0)
308                 return rc;
309
310         rc = ptllnd_parse_int_tunable(&plni->plni_msgs_spare,
311                                       "PTLLND_MSGS_SPARE", 256);
312         if (rc != 0)
313                 return rc;
314
315         rc = ptllnd_parse_int_tunable(&plni->plni_peer_hash_size,
316                                       "PTLLND_PEER_HASH_SIZE", 101);
317         if (rc != 0)
318                 return rc;
319
320
321         rc = ptllnd_parse_int_tunable(&plni->plni_eq_size,
322                                       "PTLLND_EQ_SIZE", 1024);
323         if (rc != 0)
324                 return rc;
325
326         rc = ptllnd_parse_int_tunable(&plni->plni_checksum,
327                                       "PTLLND_CHECKSUM", 0);
328         if (rc != 0)
329                 return rc;
330
331         rc = ptllnd_parse_int_tunable(&plni->plni_max_tx_history,
332                                       "PTLLND_TX_HISTORY",
333                                       plni->plni_debug ? 1024 : 0);
334         if (rc != 0)
335                 return rc;
336
337         rc = ptllnd_parse_int_tunable(&plni->plni_abort_on_protocol_mismatch,
338                                       "PTLLND_ABORT_ON_PROTOCOL_MISMATCH", 1);
339         if (rc != 0)
340                 return rc;
341
342         rc = ptllnd_parse_int_tunable(&plni->plni_abort_on_nak,
343                                       "PTLLND_ABORT_ON_NAK", 0);
344         if (rc != 0)
345                 return rc;
346
347         rc = ptllnd_parse_int_tunable(&plni->plni_dump_on_nak,
348                                       "PTLLND_DUMP_ON_NAK", plni->plni_debug);
349         if (rc != 0)
350                 return rc;
351
352         rc = ptllnd_parse_int_tunable(&plni->plni_watchdog_interval,
353                                       "PTLLND_WATCHDOG_INTERVAL", 1);
354         if (rc != 0)
355                 return rc;
356         if (plni->plni_watchdog_interval <= 0)
357                 plni->plni_watchdog_interval = 1;
358
359         rc = ptllnd_parse_int_tunable(&plni->plni_timeout,
360                                       "PTLLND_TIMEOUT", 50);
361         if (rc != 0)
362                 return rc;
363
364         rc = ptllnd_parse_int_tunable(&plni->plni_long_wait,
365                                       "PTLLND_LONG_WAIT",
366                                       plni->plni_debug ? 5 : plni->plni_timeout);
367         if (rc != 0)
368                 return rc;
369         plni->plni_long_wait *= 1000;           /* convert to mS */
370
371         plni->plni_max_msg_size = max_msg_size & ~7;
372         if (plni->plni_max_msg_size < PTLLND_MIN_BUFFER_SIZE)
373                 plni->plni_max_msg_size = PTLLND_MIN_BUFFER_SIZE;
374         CLASSERT ((PTLLND_MIN_BUFFER_SIZE & 7) == 0);
375         CLASSERT (sizeof(kptl_msg_t) <= PTLLND_MIN_BUFFER_SIZE);
376
377         plni->plni_buffer_size = plni->plni_max_msg_size * msgs_per_buffer;
378
379         CDEBUG(D_NET, "portal          = %d\n",plni->plni_portal);
380         CDEBUG(D_NET, "ptllnd_pid      = %d\n",plni->plni_ptllnd_pid);
381         CDEBUG(D_NET, "max_msg_size    = %d\n",max_msg_size);
382         CDEBUG(D_NET, "msgs_per_buffer = %d\n",msgs_per_buffer);
383         CDEBUG(D_NET, "msgs_spare      = %d\n",plni->plni_msgs_spare);
384         CDEBUG(D_NET, "peer_hash_size  = %d\n",plni->plni_peer_hash_size);
385         CDEBUG(D_NET, "eq_size         = %d\n",plni->plni_eq_size);
386         CDEBUG(D_NET, "max_msg_size    = %d\n",plni->plni_max_msg_size);
387         CDEBUG(D_NET, "buffer_size     = %d\n",plni->plni_buffer_size);
388
389         return 0;
390 }
391
392 ptllnd_buffer_t *
393 ptllnd_create_buffer (lnet_ni_t *ni)
394 {
395         ptllnd_ni_t     *plni = ni->ni_data;
396         ptllnd_buffer_t *buf;
397
398         LIBCFS_ALLOC(buf, sizeof(*buf));
399         if (buf == NULL) {
400                 CERROR("Can't allocate buffer descriptor\n");
401                 return NULL;
402         }
403
404         buf->plb_ni = ni;
405         buf->plb_posted = 0;
406         CFS_INIT_LIST_HEAD(&buf->plb_list);
407
408         LIBCFS_ALLOC(buf->plb_buffer, plni->plni_buffer_size);
409         if (buf->plb_buffer == NULL) {
410                 CERROR("Can't allocate buffer size %d\n",
411                        plni->plni_buffer_size);
412                 LIBCFS_FREE(buf, sizeof(*buf));
413                 return NULL;
414         }
415
416         cfs_list_add(&buf->plb_list, &plni->plni_buffers);
417         plni->plni_nbuffers++;
418
419         return buf;
420 }
421
422 void
423 ptllnd_destroy_buffer (ptllnd_buffer_t *buf)
424 {
425         ptllnd_ni_t     *plni = buf->plb_ni->ni_data;
426
427         LASSERT (!buf->plb_posted);
428
429         plni->plni_nbuffers--;
430         cfs_list_del(&buf->plb_list);
431         LIBCFS_FREE(buf->plb_buffer, plni->plni_buffer_size);
432         LIBCFS_FREE(buf, sizeof(*buf));
433 }
434
435 int
436 ptllnd_size_buffers (lnet_ni_t *ni, int delta)
437 {
438         ptllnd_ni_t     *plni = ni->ni_data;
439         ptllnd_buffer_t *buf;
440         int              nmsgs;
441         int              nbufs;
442         int              rc;
443
444         CDEBUG(D_NET, "nposted_buffers = %d (before)\n",plni->plni_nposted_buffers);
445         CDEBUG(D_NET, "nbuffers = %d (before)\n",plni->plni_nbuffers);
446
447         plni->plni_nmsgs += delta;
448         LASSERT(plni->plni_nmsgs >= 0);
449
450         nmsgs = plni->plni_nmsgs + plni->plni_msgs_spare;
451
452         nbufs = (nmsgs * plni->plni_max_msg_size + plni->plni_buffer_size - 1) /
453                 plni->plni_buffer_size;
454
455         while (nbufs > plni->plni_nbuffers) {
456                 buf = ptllnd_create_buffer(ni);
457
458                 if (buf == NULL)
459                         return -ENOMEM;
460
461                 rc = ptllnd_post_buffer(buf);
462                 if (rc != 0) {
463                         /* TODO - this path seems to orpahn the buffer
464                          * in a state where its not posted and will never be
465                          * However it does not leak the buffer as it's
466                          * already been put onto the global buffer list
467                          * and will be cleaned up
468                          */
469                         return rc;
470                 }
471         }
472
473         CDEBUG(D_NET, "nposted_buffers = %d (after)\n",plni->plni_nposted_buffers);
474         CDEBUG(D_NET, "nbuffers = %d (after)\n",plni->plni_nbuffers);
475         return 0;
476 }
477
478 void
479 ptllnd_destroy_buffers (lnet_ni_t *ni)
480 {
481         ptllnd_ni_t       *plni = ni->ni_data;
482         ptllnd_buffer_t   *buf;
483         cfs_list_t        *tmp;
484         cfs_list_t        *nxt;
485
486         CDEBUG(D_NET, "nposted_buffers = %d (before)\n",plni->plni_nposted_buffers);
487         CDEBUG(D_NET, "nbuffers = %d (before)\n",plni->plni_nbuffers);
488
489         cfs_list_for_each_safe(tmp, nxt, &plni->plni_buffers) {
490                 buf = cfs_list_entry(tmp, ptllnd_buffer_t, plb_list);
491
492                 //CDEBUG(D_NET, "buf=%p posted=%d\n",buf,buf->plb_posted);
493
494                 LASSERT (plni->plni_nbuffers > 0);
495                 if (buf->plb_posted) {
496                         time_t   start = cfs_time_current_sec();
497                         int      w = plni->plni_long_wait;
498
499                         LASSERT (plni->plni_nposted_buffers > 0);
500
501 #ifdef LUSTRE_PORTALS_UNLINK_SEMANTICS
502                         (void) PtlMDUnlink(buf->plb_md);
503
504                         while (buf->plb_posted) {
505                                 if (w > 0 && cfs_time_current_sec() > start + w/1000) {
506                                         CWARN("Waited %ds to unlink buffer\n",
507                                               (int)(cfs_time_current_sec() - start));
508                                         w *= 2;
509                                 }
510                                 ptllnd_wait(ni, w);
511                         }
512 #else
513                         while (buf->plb_posted) {
514                                 rc = PtlMDUnlink(buf->plb_md);
515                                 if (rc == PTL_OK) {
516                                         buf->plb_posted = 0;
517                                         plni->plni_nposted_buffers--;
518                                         break;
519                                 }
520                                 LASSERT (rc == PTL_MD_IN_USE);
521                                 if (w > 0 && cfs_time_current_sec() > start + w/1000) {
522                                         CWARN("Waited %ds to unlink buffer\n",
523                                               cfs_time_current_sec() - start);
524                                         w *= 2;
525                                 }
526                                 ptllnd_wait(ni, w);
527                         }
528 #endif
529                 }
530                 ptllnd_destroy_buffer(buf);
531         }
532
533         CDEBUG(D_NET, "nposted_buffers = %d (after)\n",plni->plni_nposted_buffers);
534         CDEBUG(D_NET, "nbuffers = %d (after)\n",plni->plni_nbuffers);
535
536         LASSERT (plni->plni_nposted_buffers == 0);
537         LASSERT (plni->plni_nbuffers == 0);
538 }
539
540 int
541 ptllnd_create_peer_hash (lnet_ni_t *ni)
542 {
543         ptllnd_ni_t *plni = ni->ni_data;
544         int          i;
545
546         plni->plni_npeers = 0;
547
548         LIBCFS_ALLOC(plni->plni_peer_hash,
549                      plni->plni_peer_hash_size * sizeof(*plni->plni_peer_hash));
550         if (plni->plni_peer_hash == NULL) {
551                 CERROR("Can't allocate ptllnd peer hash (size %d)\n",
552                        plni->plni_peer_hash_size);
553                 return -ENOMEM;
554         }
555
556         for (i = 0; i < plni->plni_peer_hash_size; i++)
557                 CFS_INIT_LIST_HEAD(&plni->plni_peer_hash[i]);
558
559         return 0;
560 }
561
562 void
563 ptllnd_destroy_peer_hash (lnet_ni_t *ni)
564 {
565         ptllnd_ni_t    *plni = ni->ni_data;
566         int             i;
567
568         LASSERT( plni->plni_npeers == 0);
569
570         for (i = 0; i < plni->plni_peer_hash_size; i++)
571                 LASSERT (cfs_list_empty(&plni->plni_peer_hash[i]));
572
573         LIBCFS_FREE(plni->plni_peer_hash,
574                     plni->plni_peer_hash_size * sizeof(*plni->plni_peer_hash));
575 }
576
577 void
578 ptllnd_close_peers (lnet_ni_t *ni)
579 {
580         ptllnd_ni_t    *plni = ni->ni_data;
581         ptllnd_peer_t  *plp;
582         int             i;
583
584         for (i = 0; i < plni->plni_peer_hash_size; i++)
585                 while (!cfs_list_empty(&plni->plni_peer_hash[i])) {
586                         plp = cfs_list_entry(plni->plni_peer_hash[i].next,
587                                              ptllnd_peer_t, plp_list);
588
589                         ptllnd_close_peer(plp, 0);
590                 }
591 }
592
593 int
594 ptllnd_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg)
595 {
596         switch (cmd) {
597         case IOC_LIBCFS_DEBUG_PEER:
598                 ptllnd_dump_debug(ni, *((lnet_process_id_t *)arg));
599                 return 0;
600
601         default:
602                 return -EINVAL;
603         }
604 }
605
606 __u64
607 ptllnd_get_timestamp(void)
608 {
609         struct timeval  tv;
610         int             rc = gettimeofday(&tv, NULL);
611
612         LASSERT (rc == 0);
613         return ((__u64)tv.tv_sec) * 1000000 + tv.tv_usec;
614 }
615
616 void
617 ptllnd_shutdown (lnet_ni_t *ni)
618 {
619         ptllnd_ni_t *plni = ni->ni_data;
620         int          rc;
621         time_t       start = cfs_time_current_sec();
622         int          w = plni->plni_long_wait;
623
624         LASSERT (ptllnd_ni_count == 1);
625         plni->plni_max_tx_history = 0;
626
627         ptllnd_cull_tx_history(plni);
628
629         ptllnd_close_peers(ni);
630         ptllnd_destroy_buffers(ni);
631
632         while (plni->plni_npeers > 0) {
633                 if (w > 0 && cfs_time_current_sec() > start + w/1000) {
634                         CWARN("Waited %ds for peers to shutdown\n",
635                               (int)(cfs_time_current_sec() - start));
636                         w *= 2;
637                 }
638                 ptllnd_wait(ni, w);
639         }
640
641         LASSERT (plni->plni_ntxs == 0);
642         LASSERT (plni->plni_nrxs == 0);
643
644         rc = PtlEQFree(plni->plni_eqh);
645         LASSERT (rc == PTL_OK);
646
647         rc = PtlNIFini(plni->plni_nih);
648         LASSERT (rc == PTL_OK);
649
650         ptllnd_destroy_peer_hash(ni);
651         LIBCFS_FREE(plni, sizeof(*plni));
652         ptllnd_ni_count--;
653 }
654
655 int
656 ptllnd_startup (lnet_ni_t *ni)
657 {
658         ptllnd_ni_t *plni;
659         int          rc;
660
661         /* could get limits from portals I guess... */
662         ni->ni_maxtxcredits =
663         ni->ni_peertxcredits = 1000;
664
665         if (ptllnd_ni_count != 0) {
666                 CERROR("Can't have > 1 instance of ptllnd\n");
667                 return -EPERM;
668         }
669
670         ptllnd_ni_count++;
671
672         rc = ptllnd_history_init();
673         if (rc != 0) {
674                 CERROR("Can't init history\n");
675                 goto failed0;
676         }
677
678         LIBCFS_ALLOC(plni, sizeof(*plni));
679         if (plni == NULL) {
680                 CERROR("Can't allocate ptllnd state\n");
681                 rc = -ENOMEM;
682                 goto failed0;
683         }
684
685         ni->ni_data = plni;
686
687         plni->plni_stamp = ptllnd_get_timestamp();
688         plni->plni_nrxs = 0;
689         plni->plni_ntxs = 0;
690         plni->plni_ntx_history = 0;
691         plni->plni_watchdog_peeridx = 0;
692         plni->plni_watchdog_nextt = cfs_time_current_sec();
693         CFS_INIT_LIST_HEAD(&plni->plni_zombie_txs);
694         CFS_INIT_LIST_HEAD(&plni->plni_tx_history);
695
696         /*
697          *  Initilize buffer related data structures
698          */
699         CFS_INIT_LIST_HEAD(&plni->plni_buffers);
700         plni->plni_nbuffers = 0;
701         plni->plni_nposted_buffers = 0;
702
703         rc = ptllnd_get_tunables(ni);
704         if (rc != 0)
705                 goto failed1;
706
707         rc = ptllnd_create_peer_hash(ni);
708         if (rc != 0)
709                 goto failed1;
710
711         /* NB I most probably won't get the PID I requested here.  It doesn't
712          * matter because I don't need a fixed PID (only connection acceptors
713          * need a "well known" PID). */
714
715         rc = PtlNIInit(PTL_IFACE_DEFAULT, plni->plni_ptllnd_pid,
716                        NULL, NULL, &plni->plni_nih);
717         if (rc != PTL_OK && rc != PTL_IFACE_DUP) {
718                 CERROR("PtlNIInit failed: %s(%d)\n",
719                        ptllnd_errtype2str(rc), rc);
720                 rc = -ENODEV;
721                 goto failed2;
722         }
723
724         rc = PtlEQAlloc(plni->plni_nih, plni->plni_eq_size,
725                         PTL_EQ_HANDLER_NONE, &plni->plni_eqh);
726         if (rc != PTL_OK) {
727                 CERROR("PtlEQAlloc failed: %s(%d)\n",
728                        ptllnd_errtype2str(rc), rc);
729                 rc = -ENODEV;
730                 goto failed3;
731         }
732
733         /*
734          * Fetch the Portals NID
735          */
736         rc = PtlGetId(plni->plni_nih, &plni->plni_portals_id);
737         if (rc != PTL_OK) {
738                 CERROR ("PtlGetID failed : %s(%d)\n",
739                         ptllnd_errtype2str(rc), rc);
740                 rc = -EINVAL;
741                 goto failed4;
742         }
743
744         /*
745          * Create the new NID.  Based on the LND network type
746          * and the lower ni's address data.
747          */
748         ni->ni_nid = ptllnd_ptl2lnetnid(ni, plni->plni_portals_id.nid);
749
750         CDEBUG(D_NET, "ptl id  =%s\n", ptllnd_ptlid2str(plni->plni_portals_id));
751         CDEBUG(D_NET, "lnet id =%s (passed back)\n",
752                libcfs_id2str((lnet_process_id_t) {
753                        .nid = ni->ni_nid, .pid = the_lnet.ln_pid}));
754
755         rc = ptllnd_size_buffers(ni, 0);
756         if (rc != 0)
757                 goto failed4;
758
759         return 0;
760
761  failed4:
762         ptllnd_destroy_buffers(ni);
763         PtlEQFree(plni->plni_eqh);
764  failed3:
765         PtlNIFini(plni->plni_nih);
766  failed2:
767         ptllnd_destroy_peer_hash(ni);
768  failed1:
769         LIBCFS_FREE(plni, sizeof(*plni));
770  failed0:
771         ptllnd_history_fini();
772         ptllnd_ni_count--;
773         CDEBUG(D_NET, "<<< rc=%d\n",rc);
774         return rc;
775 }
776
777 const char *ptllnd_evtype2str(int type)
778 {
779 #define DO_TYPE(x) case x: return #x;
780         switch(type)
781         {
782                 DO_TYPE(PTL_EVENT_GET_START);
783                 DO_TYPE(PTL_EVENT_GET_END);
784                 DO_TYPE(PTL_EVENT_PUT_START);
785                 DO_TYPE(PTL_EVENT_PUT_END);
786                 DO_TYPE(PTL_EVENT_REPLY_START);
787                 DO_TYPE(PTL_EVENT_REPLY_END);
788                 DO_TYPE(PTL_EVENT_ACK);
789                 DO_TYPE(PTL_EVENT_SEND_START);
790                 DO_TYPE(PTL_EVENT_SEND_END);
791                 DO_TYPE(PTL_EVENT_UNLINK);
792         default:
793                 return "<unknown event type>";
794         }
795 #undef DO_TYPE
796 }
797
798 const char *ptllnd_msgtype2str(int type)
799 {
800 #define DO_TYPE(x) case x: return #x;
801         switch(type)
802         {
803                 DO_TYPE(PTLLND_MSG_TYPE_INVALID);
804                 DO_TYPE(PTLLND_MSG_TYPE_PUT);
805                 DO_TYPE(PTLLND_MSG_TYPE_GET);
806                 DO_TYPE(PTLLND_MSG_TYPE_IMMEDIATE);
807                 DO_TYPE(PTLLND_MSG_TYPE_HELLO);
808                 DO_TYPE(PTLLND_MSG_TYPE_NOOP);
809                 DO_TYPE(PTLLND_MSG_TYPE_NAK);
810         default:
811                 return "<unknown msg type>";
812         }
813 #undef DO_TYPE
814 }
815
816 const char *ptllnd_errtype2str(int type)
817 {
818 #define DO_TYPE(x) case x: return #x;
819         switch(type)
820         {
821                 DO_TYPE(PTL_OK);
822                 DO_TYPE(PTL_SEGV);
823                 DO_TYPE(PTL_NO_SPACE);
824                 DO_TYPE(PTL_ME_IN_USE);
825                 DO_TYPE(PTL_NAL_FAILED);
826                 DO_TYPE(PTL_NO_INIT);
827                 DO_TYPE(PTL_IFACE_DUP);
828                 DO_TYPE(PTL_IFACE_INVALID);
829                 DO_TYPE(PTL_HANDLE_INVALID);
830                 DO_TYPE(PTL_MD_INVALID);
831                 DO_TYPE(PTL_ME_INVALID);
832                 DO_TYPE(PTL_PROCESS_INVALID);
833                 DO_TYPE(PTL_PT_INDEX_INVALID);
834                 DO_TYPE(PTL_SR_INDEX_INVALID);
835                 DO_TYPE(PTL_EQ_INVALID);
836                 DO_TYPE(PTL_EQ_DROPPED);
837                 DO_TYPE(PTL_EQ_EMPTY);
838                 DO_TYPE(PTL_MD_NO_UPDATE);
839                 DO_TYPE(PTL_FAIL);
840                 DO_TYPE(PTL_AC_INDEX_INVALID);
841                 DO_TYPE(PTL_MD_ILLEGAL);
842                 DO_TYPE(PTL_ME_LIST_TOO_LONG);
843                 DO_TYPE(PTL_MD_IN_USE);
844                 DO_TYPE(PTL_NI_INVALID);
845                 DO_TYPE(PTL_PID_INVALID);
846                 DO_TYPE(PTL_PT_FULL);
847                 DO_TYPE(PTL_VAL_FAILED);
848                 DO_TYPE(PTL_NOT_IMPLEMENTED);
849                 DO_TYPE(PTL_NO_ACK);
850                 DO_TYPE(PTL_EQ_IN_USE);
851                 DO_TYPE(PTL_PID_IN_USE);
852                 DO_TYPE(PTL_INV_EQ_SIZE);
853                 DO_TYPE(PTL_AGAIN);
854         default:
855                 return "<unknown error type>";
856         }
857 #undef DO_TYPE
858 }