Whamcloud - gitweb
9f086de753098952222cea8a83092b96a6fa5a44
[fs/lustre-release.git] / lnet / klnds / gmlnd / gmlnd_api.c
1 /*
2  * -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
3  * vim:expandtab:shiftwidth=8:tabstop=8:
4  *
5  * GPL HEADER START
6  *
7  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 only,
11  * as published by the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License version 2 for more details (a copy is included
17  * in the LICENSE file that accompanied this code).
18  *
19  * You should have received a copy of the GNU General Public License
20  * version 2 along with this program; If not, see [sun.com URL with a
21  * copy of GPLv2].
22  *
23  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
24  * CA 95054 USA or visit www.sun.com if you need additional information or
25  * have any questions.
26  *
27  * GPL HEADER END
28  */
29 /*
30  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
31  * Use is subject to license terms.
32  *
33  * Copyright (c) 2003 Los Alamos National Laboratory (LANL)
34  */
35 /*
36  * This file is part of Lustre, http://www.lustre.org/
37  * Lustre is a trademark of Sun Microsystems, Inc.
38  */
39
40 /*
41  *      Implements the API NAL functions
42  */
43
44 #include "gmlnd.h"
45
46 lnd_t the_gmlnd =
47 {
48         .lnd_type            = GMLND,
49         .lnd_startup         = gmnal_startup,
50         .lnd_shutdown        = gmnal_shutdown,
51         .lnd_ctl             = gmnal_ctl,
52         .lnd_send            = gmnal_send,
53         .lnd_recv            = gmnal_recv,
54 };
55
56 gmnal_ni_t *the_gmni = NULL;
57
58 int
59 gmnal_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg)
60 {
61         struct libcfs_ioctl_data *data = arg;
62
63         switch (cmd) {
64         case IOC_LIBCFS_REGISTER_MYNID:
65                 if (data->ioc_nid == ni->ni_nid)
66                         return 0;
67
68                 LASSERT (LNET_NIDNET(data->ioc_nid) == LNET_NIDNET(ni->ni_nid));
69
70                 CERROR("obsolete IOC_LIBCFS_REGISTER_MYNID for %s(%s)\n",
71                        libcfs_nid2str(data->ioc_nid),
72                        libcfs_nid2str(ni->ni_nid));
73                 return 0;
74
75         default:
76                 return (-EINVAL);
77         }
78 }
79
80 int
81 gmnal_set_local_nid (gmnal_ni_t *gmni)
82 {
83         lnet_ni_t       *ni = gmni->gmni_ni;
84         __u32            local_gmid;
85         __u32            global_gmid;
86         gm_status_t      gm_status;
87
88         /* Called before anything initialised: no need to lock */
89         gm_status = gm_get_node_id(gmni->gmni_port, &local_gmid);
90         if (gm_status != GM_SUCCESS)
91                 return 0;
92
93         CDEBUG(D_NET, "Local node id is [%u]\n", local_gmid);
94
95         gm_status = gm_node_id_to_global_id(gmni->gmni_port, 
96                                             local_gmid, 
97                                             &global_gmid);
98         if (gm_status != GM_SUCCESS)
99                 return 0;
100
101         CDEBUG(D_NET, "Global node id is [%u]\n", global_gmid);
102
103         ni->ni_nid = LNET_MKNID(LNET_NIDNET(ni->ni_nid), global_gmid);
104         return 1;
105 }
106
107 void
108 gmnal_shutdown(lnet_ni_t *ni)
109 {
110         gmnal_ni_t *gmni = ni->ni_data;
111
112         CDEBUG(D_TRACE, "gmnal_api_shutdown: gmni [%p]\n", gmni);
113
114         LASSERT (gmni == the_gmni);
115
116         /* stop processing messages */
117         gmnal_stop_threads(gmni);
118
119         /* stop all network callbacks */
120         gm_close(gmni->gmni_port);
121         gmni->gmni_port = NULL;
122
123         gm_finalize();
124
125         gmnal_free_ltxbufs(gmni);
126         gmnal_free_txs(gmni);
127         gmnal_free_rxs(gmni);
128
129         LIBCFS_FREE(gmni, sizeof(*gmni));
130
131         the_gmni = NULL;
132         PORTAL_MODULE_UNUSE;
133 }
134
135 int
136 gmnal_startup(lnet_ni_t *ni)
137 {
138         gmnal_ni_t  *gmni = NULL;
139         gmnal_rx_t  *rx = NULL;
140         gm_status_t  gm_status;
141         int          rc;
142
143         LASSERT (ni->ni_lnd == &the_gmlnd);
144
145         ni->ni_maxtxcredits = *gmnal_tunables.gm_credits;
146         ni->ni_peertxcredits = *gmnal_tunables.gm_peer_credits;
147
148         if (the_gmni != NULL) {
149                 CERROR("Only 1 instance supported\n");
150                 return -EINVAL;
151         }
152
153         LIBCFS_ALLOC(gmni, sizeof(*gmni));
154         if (gmni == NULL) {
155                 CERROR("can't allocate gmni\n");
156                 return -ENOMEM;
157         }
158
159         ni->ni_data = gmni;
160
161         memset(gmni, 0, sizeof(*gmni));
162         gmni->gmni_ni = ni;
163         spin_lock_init(&gmni->gmni_tx_lock);
164         spin_lock_init(&gmni->gmni_gm_lock);
165         INIT_LIST_HEAD(&gmni->gmni_idle_txs);
166         INIT_LIST_HEAD(&gmni->gmni_idle_ltxbs);
167         INIT_LIST_HEAD(&gmni->gmni_buf_txq);
168         INIT_LIST_HEAD(&gmni->gmni_cred_txq);
169         sema_init(&gmni->gmni_rx_mutex, 1);
170         PORTAL_MODULE_USE;
171
172         /*
173          * initialise the interface,
174          */
175         CDEBUG(D_NET, "Calling gm_init\n");
176         if (gm_init() != GM_SUCCESS) {
177                 CERROR("call to gm_init failed\n");
178                 goto failed_0;
179         }
180
181         CDEBUG(D_NET, "Calling gm_open with port [%d], version [%d]\n",
182                *gmnal_tunables.gm_port, GM_API_VERSION);
183
184         gm_status = gm_open(&gmni->gmni_port, 0, *gmnal_tunables.gm_port, 
185                             "gmnal", GM_API_VERSION);
186
187         if (gm_status != GM_SUCCESS) {
188                 CERROR("Can't open GM port %d: %d (%s)\n",
189                        *gmnal_tunables.gm_port, gm_status, 
190                        gmnal_gmstatus2str(gm_status));
191                 goto failed_1;
192         }
193
194         CDEBUG(D_NET,"gm_open succeeded port[%p]\n",gmni->gmni_port);
195
196         if (!gmnal_set_local_nid(gmni))
197                 goto failed_2;
198
199         CDEBUG(D_NET, "portals_nid is %s\n", libcfs_nid2str(ni->ni_nid));
200
201         gmni->gmni_large_msgsize = 
202                 offsetof(gmnal_msg_t, gmm_u.immediate.gmim_payload[LNET_MAX_PAYLOAD]);
203         gmni->gmni_large_gmsize = 
204                 gm_min_size_for_length(gmni->gmni_large_msgsize);
205         gmni->gmni_large_pages =
206                 (gmni->gmni_large_msgsize + PAGE_SIZE - 1)/PAGE_SIZE;
207
208         gmni->gmni_small_msgsize = MIN(GM_MTU, PAGE_SIZE);
209         gmni->gmni_small_gmsize = 
210                 gm_min_size_for_length(gmni->gmni_small_msgsize);
211
212         gmni->gmni_netaddr_base = GMNAL_NETADDR_BASE;
213         gmni->gmni_netaddr_size = 0;
214
215         CDEBUG(D_NET, "Msg size %08x/%08x [%d/%d]\n", 
216                gmni->gmni_large_msgsize, gmni->gmni_small_msgsize,
217                gmni->gmni_large_gmsize, gmni->gmni_small_gmsize);
218
219         if (gmnal_alloc_rxs(gmni) != 0) {
220                 CERROR("Failed to allocate rx descriptors\n");
221                 goto failed_2;
222         }
223
224         if (gmnal_alloc_txs(gmni) != 0) {
225                 CERROR("Failed to allocate tx descriptors\n");
226                 goto failed_2;
227         }
228
229         if (gmnal_alloc_ltxbufs(gmni) != 0) {
230                 CERROR("Failed to allocate large tx buffers\n");
231                 goto failed_2;
232         }
233
234         rc = gmnal_start_threads(gmni);
235         if (rc != 0) {
236                 CERROR("Can't start threads: %d\n", rc);
237                 goto failed_2;
238         }
239
240         /* Start listening */
241         for (rx = gmni->gmni_rxs; rx != NULL; rx = rx->rx_next)
242                 gmnal_post_rx(gmni, rx);
243
244         the_gmni = gmni;
245
246         CDEBUG(D_NET, "gmnal_init finished\n");
247         return 0;
248
249  failed_2:
250         gm_close(gmni->gmni_port);
251         gmni->gmni_port = NULL;
252
253  failed_1:
254         gm_finalize();
255
256  failed_0:
257         /* safe to free descriptors after network has been shut down */
258         gmnal_free_ltxbufs(gmni);
259         gmnal_free_txs(gmni);
260         gmnal_free_rxs(gmni);
261
262         LIBCFS_FREE(gmni, sizeof(*gmni));
263         PORTAL_MODULE_UNUSE;
264
265         return -EIO;
266 }
267
268 /* 
269  *        Called when module loaded
270  */
271 int gmnal_init(void)
272 {
273         lnet_register_lnd(&the_gmlnd);
274         return 0;
275 }
276
277 /*
278  *      Called when module removed
279  */
280 void gmnal_fini()
281 {
282         lnet_unregister_lnd(&the_gmlnd);
283 }