Whamcloud - gitweb
* Landed b_cray_portals_merge.
[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 #include <portals/api-support.h>
27
28 int ptl_init;
29
30 /* Put some magic in the NI handle so uninitialised/zeroed handles are easy
31  * to spot */
32 #define NI_HANDLE_MAGIC  0xebc0de00
33 #define NI_HANDLE_MASK   0x000000ff
34
35 static struct nal_t *ptl_nal_table[NAL_MAX_NR];
36
37 #ifdef __KERNEL__
38 DECLARE_MUTEX(ptl_mutex);
39
40 static void ptl_mutex_enter (void) 
41 {
42         down (&ptl_mutex);
43 }
44
45 static void ptl_mutex_exit (void)
46 {
47         up (&ptl_mutex);
48 }
49 #else
50 static void ptl_mutex_enter (void)
51 {
52 }
53
54 static void ptl_mutex_exit (void) 
55 {
56 }
57 #endif
58
59 nal_t *ptl_hndl2nal(ptl_handle_any_t *handle)
60 {
61         unsigned int idx = handle->nal_idx;
62
63         /* XXX we really rely on the caller NOT racing with interface
64          * setup/teardown.  That ensures her NI handle can't get
65          * invalidated out from under her (or worse, swapped for a
66          * completely different interface!) */
67
68         if (((idx ^ NI_HANDLE_MAGIC) & ~NI_HANDLE_MASK) != 0)
69                 return NULL;
70
71         idx &= NI_HANDLE_MASK;
72         
73         if (idx >= NAL_MAX_NR ||
74             ptl_nal_table[idx] == NULL ||
75             ptl_nal_table[idx]->nal_refct == 0)
76                 return NULL;
77
78         return ptl_nal_table[idx];
79 }
80
81 int ptl_register_nal (ptl_interface_t interface, nal_t *nal)
82 {
83         int    rc;
84         
85         ptl_mutex_enter();
86         
87         if (interface < 0 || interface >= NAL_MAX_NR)
88                 rc = PTL_IFACE_INVALID;
89         else if (ptl_nal_table[interface] != NULL)
90                 rc = PTL_IFACE_DUP;
91         else {
92                 rc = PTL_OK;
93                 ptl_nal_table[interface] = nal;
94                 LASSERT(nal->nal_refct == 0);
95         }
96
97         ptl_mutex_exit();
98         return (rc);
99 }
100
101 void ptl_unregister_nal (ptl_interface_t interface)
102 {
103         LASSERT(interface >= 0 && interface < NAL_MAX_NR);
104         LASSERT(ptl_nal_table[interface] != NULL);
105         LASSERT(ptl_nal_table[interface]->nal_refct == 0);
106         
107         ptl_mutex_enter();
108         
109         ptl_nal_table[interface] = NULL;
110
111         ptl_mutex_exit();
112 }
113
114 int ptl_ni_init(void)
115 {
116         /* If this assertion fails, we need more bits in NI_HANDLE_MASK and
117          * to shift NI_HANDLE_MAGIC left appropriately */
118         LASSERT (NAL_MAX_NR <= (NI_HANDLE_MASK + 1));
119         
120         ptl_mutex_enter();
121
122         if (!ptl_init) {
123                 /* NULL pointers, clear flags */
124                 memset(ptl_nal_table, 0, sizeof(ptl_nal_table));
125 #ifndef __KERNEL__
126                 /* Kernel NALs register themselves when their module loads,
127                  * and unregister themselves when their module is unloaded.
128                  * Userspace NALs, are plugged in explicitly here... */
129                 {
130                         extern nal_t procapi_nal;
131
132                         /* XXX pretend it's socknal to keep liblustre happy... */
133                         ptl_nal_table[SOCKNAL] = &procapi_nal;
134                         LASSERT (procapi_nal.nal_refct == 0);
135                 }
136 #endif
137                 ptl_init = 1;
138         }
139
140         ptl_mutex_exit();
141         
142         return PTL_OK;
143 }
144
145 void ptl_ni_fini(void)
146 {
147         nal_t  *nal;
148         int     i;
149
150         ptl_mutex_enter();
151
152         if (ptl_init) {
153                 for (i = 0; i < NAL_MAX_NR; i++) {
154
155                         nal = ptl_nal_table[i];
156                         if (nal == NULL)
157                                 continue;
158                         
159                         if (nal->nal_refct != 0) {
160                                 CWARN("NAL %d has outstanding refcount %d\n",
161                                       i, nal->nal_refct);
162                                 nal->shutdown(nal);
163                         }
164                         
165                         ptl_nal_table[i] = NULL;
166                 }
167
168                 ptl_init = 0;
169         }
170         
171         ptl_mutex_exit();
172 }
173
174 int PtlNIInit(ptl_interface_t interface, ptl_pid_t requested_pid,
175               ptl_ni_limits_t *desired_limits, ptl_ni_limits_t *actual_limits,
176               ptl_handle_ni_t *handle)
177 {
178         nal_t *nal;
179         int    i;
180         int    rc;
181
182         if (!ptl_init)
183                 return PTL_NO_INIT;
184
185         ptl_mutex_enter ();
186
187         if (interface == PTL_IFACE_DEFAULT) {
188                 for (i = 0; i < NAL_MAX_NR; i++)
189                         if (ptl_nal_table[i] != NULL) {
190                                 interface = i;
191                                 break;
192                         }
193                 /* NB if no interfaces are registered, 'interface' will
194                  * fail the valid test below */
195         }
196         
197         if (interface < 0 || 
198             interface >= NAL_MAX_NR ||
199             ptl_nal_table[interface] == NULL) {
200                 GOTO(out, rc = PTL_IFACE_INVALID);
201         }
202
203         nal = ptl_nal_table[interface];
204
205         CDEBUG(D_OTHER, "Starting up NAL (%d) refs %d\n", interface, nal->nal_refct);
206         rc = nal->startup(nal, requested_pid, desired_limits, actual_limits);
207
208         if (rc != PTL_OK) {
209                 CERROR("Error %d starting up NAL %d, refs %d\n", rc,
210                        interface, nal->nal_refct);
211                 GOTO(out, rc);
212         }
213         
214         if (nal->nal_refct != 0) {
215                 /* Caller gets to know if this was the first ref or not */
216                 rc = PTL_IFACE_DUP;
217         }
218         
219         nal->nal_refct++;
220         handle->nal_idx = (NI_HANDLE_MAGIC & ~NI_HANDLE_MASK) | interface;
221
222  out:
223         ptl_mutex_exit ();
224         return rc;
225 }
226
227 int PtlNIFini(ptl_handle_ni_t ni)
228 {
229         nal_t *nal;
230         int    idx;
231
232         if (!ptl_init)
233                 return PTL_NO_INIT;
234
235         ptl_mutex_enter ();
236
237         nal = ptl_hndl2nal (&ni);
238         if (nal == NULL) {
239                 ptl_mutex_exit ();
240                 return PTL_HANDLE_INVALID;
241         }
242
243         idx = ni.nal_idx & NI_HANDLE_MASK;
244
245         LASSERT(nal->nal_refct > 0);
246
247         nal->nal_refct--;
248
249         /* nal_refct == 0 tells nal->shutdown to really shut down */
250         nal->shutdown(nal);
251
252         ptl_mutex_exit ();
253         return PTL_OK;
254 }
255
256 int PtlNIHandle(ptl_handle_any_t handle_in, ptl_handle_ni_t * ni_out)
257 {
258         *ni_out = handle_in;
259
260         return PTL_OK;
261 }