1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
5 * Network Interface code
7 * Copyright (c) 2001-2003 Cluster File Systems, Inc.
8 * Copyright (c) 2001-2002 Sandia National Laboratories
10 * This file is part of Lustre, http://www.sf.net/projects/lustre/
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.
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.
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.
26 #define DEBUG_SUBSYSTEM S_PORTALS
27 #include <portals/api-support.h>
31 /* Put some magic in the NI handle so uninitialised/zeroed handles are easy
33 #define NI_HANDLE_MAGIC 0xebc0de00
34 #define NI_HANDLE_MASK 0x000000ff
36 static struct nal_t *ptl_nal_table[NAL_MAX_NR + 1];
39 DECLARE_MUTEX(ptl_mutex);
41 static void ptl_mutex_enter (void)
46 static void ptl_mutex_exit (void)
51 static void ptl_mutex_enter (void)
55 static void ptl_mutex_exit (void)
60 nal_t *ptl_hndl2nal(ptl_handle_any_t *handle)
62 unsigned int idx = handle->nal_idx;
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!) */
71 if (((idx ^ NI_HANDLE_MAGIC) & ~NI_HANDLE_MASK) != 0)
74 idx &= NI_HANDLE_MASK;
76 if (idx > NAL_MAX_NR ||
77 ptl_nal_table[idx] == NULL ||
78 ptl_nal_table[idx]->nal_refct == 0)
81 return ptl_nal_table[idx];
84 int ptl_register_nal (ptl_interface_t interface, nal_t *nal)
90 if (interface < 0 || interface > NAL_MAX_NR)
91 rc = PTL_IFACE_INVALID;
92 else if (ptl_nal_table[interface] != NULL)
96 ptl_nal_table[interface] = nal;
97 LASSERT(nal->nal_refct == 0);
104 void ptl_unregister_nal (ptl_interface_t interface)
106 LASSERT(interface >= 0 && interface <= NAL_MAX_NR);
107 LASSERT(ptl_nal_table[interface] != NULL);
108 LASSERT(ptl_nal_table[interface]->nal_refct == 0);
112 ptl_nal_table[interface] = NULL;
117 int PtlInit(int *max_interfaces)
119 LASSERT(!strcmp(ptl_err_str[PTL_MAX_ERRNO], "PTL_MAX_ERRNO"));
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));
125 if (max_interfaces != NULL)
126 *max_interfaces = NAL_MAX_NR + 1;
131 /* NULL pointers, clear flags */
132 memset(ptl_nal_table, 0, sizeof(ptl_nal_table));
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... */
138 extern nal_t procapi_nal;
140 /* XXX pretend it's socknal to keep liblustre happy... */
141 ptl_nal_table[SOCKNAL] = &procapi_nal;
142 LASSERT (procapi_nal.nal_refct == 0);
161 for (i = 0; i <= NAL_MAX_NR; i++) {
163 nal = ptl_nal_table[i];
167 if (nal->nal_refct != 0) {
168 CWARN("NAL %x has outstanding refcount %d\n",
170 nal->nal_ni_fini(nal);
173 ptl_nal_table[i] = NULL;
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)
195 if (interface == PTL_IFACE_DEFAULT) {
196 for (i = 0; i <= NAL_MAX_NR; i++)
197 if (ptl_nal_table[i] != NULL) {
201 /* NB if no interfaces are registered, 'interface' will
202 * fail the valid test below */
206 interface > NAL_MAX_NR ||
207 ptl_nal_table[interface] == NULL) {
208 GOTO(out, rc = PTL_IFACE_INVALID);
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;
215 CDEBUG(D_OTHER, "Starting up NAL (%x) refs %d\n", interface, nal->nal_refct);
216 rc = nal->nal_ni_init(nal, requested_pid, desired_limits, actual_limits);
219 CERROR("Error %d starting up NAL %x, refs %d\n", rc,
220 interface, nal->nal_refct);
224 if (nal->nal_refct != 0) {
225 /* Caller gets to know if this was the first ref or not */
230 *handle = nal->nal_handle;
238 int PtlNIFini(ptl_handle_ni_t ni)
248 nal = ptl_hndl2nal (&ni);
251 return PTL_HANDLE_INVALID;
254 idx = ni.nal_idx & NI_HANDLE_MASK;
256 LASSERT(nal->nal_refct > 0);
260 /* nal_refct == 0 tells nal->shutdown to really shut down */
261 nal->nal_ni_fini(nal);