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