Whamcloud - gitweb
- merge 2 weeks of b1_4 fixes onto HEAD
[fs/lustre-release.git] / lnet / lnet / api-ni.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * api/api-ni.c
5  * Network Interface code
6  *
7  *  Copyright (c) 2001-2003 Cluster File Systems, Inc.
8  *  Copyright (c) 2001-2002 Sandia National Laboratories
9  *
10  *   This file is part of Lustre, http://www.sf.net/projects/lustre/
11  *
12  *   Lustre is free software; you can redistribute it and/or
13  *   modify it under the terms of version 2 of the GNU General Public
14  *   License as published by the Free Software Foundation.
15  *
16  *   Lustre is distributed in the hope that it will be useful,
17  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *   GNU General Public License for more details.
20  *
21  *   You should have received a copy of the GNU General Public License
22  *   along with Lustre; if not, write to the Free Software
23  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25
26 #define DEBUG_SUBSYSTEM S_PORTALS
27 #include <portals/api-support.h>
28
29 int ptl_init;
30
31 /* Put some magic in the NI handle so uninitialised/zeroed handles are easy
32  * to spot */
33 #define NI_HANDLE_MAGIC  0xebc0de00
34 #define NI_HANDLE_MASK   0x000000ff
35
36 static struct nal_t *ptl_nal_table[NAL_MAX_NR];
37
38 #ifdef __KERNEL__
39 DECLARE_MUTEX(ptl_mutex);
40
41 static void ptl_mutex_enter (void) 
42 {
43         down (&ptl_mutex);
44 }
45
46 static void ptl_mutex_exit (void)
47 {
48         up (&ptl_mutex);
49 }
50 #else
51 static void ptl_mutex_enter (void)
52 {
53 }
54
55 static void ptl_mutex_exit (void) 
56 {
57 }
58 #endif
59
60 nal_t *ptl_hndl2nal(ptl_handle_any_t *handle)
61 {
62         unsigned int idx = handle->nal_idx;
63
64         /* XXX we really rely on the caller NOT racing with interface
65          * setup/teardown.  That ensures her NI handle can't get
66          * invalidated out from under her (or worse, swapped for a
67          * completely different interface!) */
68
69         LASSERT (ptl_init);
70
71         if (((idx ^ NI_HANDLE_MAGIC) & ~NI_HANDLE_MASK) != 0)
72                 return NULL;
73
74         idx &= NI_HANDLE_MASK;
75         
76         if (idx >= NAL_MAX_NR ||
77             ptl_nal_table[idx] == NULL ||
78             ptl_nal_table[idx]->nal_refct == 0)
79                 return NULL;
80
81         return ptl_nal_table[idx];
82 }
83
84 int ptl_register_nal (ptl_interface_t interface, nal_t *nal)
85 {
86         int    rc;
87         
88         ptl_mutex_enter();
89         
90         if (interface < 0 || interface >= NAL_MAX_NR)
91                 rc = PTL_IFACE_INVALID;
92         else if (ptl_nal_table[interface] != NULL)
93                 rc = PTL_IFACE_DUP;
94         else {
95                 rc = PTL_OK;
96                 ptl_nal_table[interface] = nal;
97                 LASSERT(nal->nal_refct == 0);
98         }
99
100         ptl_mutex_exit();
101         return (rc);
102 }
103
104 void ptl_unregister_nal (ptl_interface_t interface)
105 {
106         LASSERT(interface >= 0 && interface < NAL_MAX_NR);
107         LASSERT(ptl_nal_table[interface] != NULL);
108         LASSERT(ptl_nal_table[interface]->nal_refct == 0);
109         
110         ptl_mutex_enter();
111         
112         ptl_nal_table[interface] = NULL;
113
114         ptl_mutex_exit();
115 }
116
117 int PtlInit(int *max_interfaces)
118 {
119         LASSERT(!strcmp(ptl_err_str[PTL_MAX_ERRNO], "PTL_MAX_ERRNO"));
120
121         /* If this assertion fails, we need more bits in NI_HANDLE_MASK and
122          * to shift NI_HANDLE_MAGIC left appropriately */
123         LASSERT (NAL_MAX_NR <= (NI_HANDLE_MASK + 1));
124         
125         if (max_interfaces != NULL)
126                 *max_interfaces = NAL_MAX_NR;
127
128         ptl_mutex_enter();
129
130         if (!ptl_init) {
131                 /* NULL pointers, clear flags */
132                 memset(ptl_nal_table, 0, sizeof(ptl_nal_table));
133 #ifndef __KERNEL__
134                 /* Kernel NALs register themselves when their module loads,
135                  * and unregister themselves when their module is unloaded.
136                  * Userspace NALs, are plugged in explicitly here... */
137                 {
138                         extern nal_t procapi_nal;
139
140                         /* XXX pretend it's socknal to keep liblustre happy... */
141                         ptl_nal_table[SOCKNAL] = &procapi_nal;
142                         LASSERT (procapi_nal.nal_refct == 0);
143                 }
144 #endif
145                 ptl_init = 1;
146         }
147
148         ptl_mutex_exit();
149         
150         return PTL_OK;
151 }
152
153 void PtlFini(void)
154 {
155         nal_t  *nal;
156         int     i;
157
158         ptl_mutex_enter();
159
160         if (ptl_init) {
161                 for (i = 0; i < NAL_MAX_NR; i++) {
162
163                         nal = ptl_nal_table[i];
164                         if (nal == NULL)
165                                 continue;
166                         
167                         if (nal->nal_refct != 0) {
168                                 CWARN("NAL %d has outstanding refcount %d\n",
169                                       i, nal->nal_refct);
170                                 nal->nal_ni_fini(nal);
171                         }
172                         
173                         ptl_nal_table[i] = NULL;
174                 }
175
176                 ptl_init = 0;
177         }
178         
179         ptl_mutex_exit();
180 }
181
182 int PtlNIInit(ptl_interface_t interface, ptl_pid_t requested_pid,
183               ptl_ni_limits_t *desired_limits, ptl_ni_limits_t *actual_limits,
184               ptl_handle_ni_t *handle)
185 {
186         nal_t *nal;
187         int    i;
188         int    rc;
189
190         if (!ptl_init)
191                 return PTL_NO_INIT;
192
193         ptl_mutex_enter ();
194
195         if (interface == PTL_IFACE_DEFAULT) {
196                 for (i = 0; i < NAL_MAX_NR; i++)
197                         if (ptl_nal_table[i] != NULL) {
198                                 interface = i;
199                                 break;
200                         }
201                 /* NB if no interfaces are registered, 'interface' will
202                  * fail the valid test below */
203         }
204         
205         if (interface < 0 || 
206             interface >= NAL_MAX_NR ||
207             ptl_nal_table[interface] == NULL) {
208                 GOTO(out, rc = PTL_IFACE_INVALID);
209         }
210
211         nal = ptl_nal_table[interface];
212         nal->nal_handle.nal_idx = (NI_HANDLE_MAGIC & ~NI_HANDLE_MASK) | interface;
213         nal->nal_handle.cookie = 0;
214         
215         CDEBUG(D_OTHER, "Starting up NAL (%d) refs %d\n", interface, nal->nal_refct);
216         rc = nal->nal_ni_init(nal, requested_pid, desired_limits, actual_limits);
217
218         if (rc != PTL_OK) {
219                 CERROR("Error %d starting up NAL %d, refs %d\n", rc,
220                        interface, nal->nal_refct);
221                 GOTO(out, rc);
222         }
223         
224         if (nal->nal_refct != 0) {
225                 /* Caller gets to know if this was the first ref or not */
226                 rc = PTL_IFACE_DUP;
227         }
228         
229         nal->nal_refct++;
230         *handle = nal->nal_handle;
231
232  out:
233         ptl_mutex_exit ();
234
235         return rc;
236 }
237
238 int PtlNIFini(ptl_handle_ni_t ni)
239 {
240         nal_t *nal;
241         int    idx;
242
243         if (!ptl_init)
244                 return PTL_NO_INIT;
245
246         ptl_mutex_enter ();
247
248         nal = ptl_hndl2nal (&ni);
249         if (nal == NULL) {
250                 ptl_mutex_exit ();
251                 return PTL_HANDLE_INVALID;
252         }
253
254         idx = ni.nal_idx & NI_HANDLE_MASK;
255
256         LASSERT(nal->nal_refct > 0);
257
258         nal->nal_refct--;
259
260         /* nal_refct == 0 tells nal->shutdown to really shut down */
261         nal->nal_ni_fini(nal);
262
263         ptl_mutex_exit ();
264         return PTL_OK;
265 }