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