1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (c) 2003 Los Alamos National Laboratory (LANL)
6 * This file is part of Lustre, http://www.lustre.org/
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.
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.
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.
23 * Implements the API NAL functions
30 gmnal_data_t *global_nal_data = NULL;
31 #define GLOBAL_NID_STR_LEN 16
32 char global_nid_str[GLOBAL_NID_STR_LEN] = {0};
35 * Write the global nid /proc/sys/gmnal/globalnid
37 #define GMNAL_SYSCTL 201
38 #define GMNAL_SYSCTL_GLOBALNID 1
40 static ctl_table gmnal_sysctl_table[] = {
41 {GMNAL_SYSCTL_GLOBALNID, "globalnid",
42 global_nid_str, GLOBAL_NID_STR_LEN,
43 0444, NULL, &proc_dostring},
48 static ctl_table gmnalnal_top_sysctl_table[] = {
49 {GMNAL_SYSCTL, "gmnal", NULL, 0, 0555, gmnal_sysctl_table},
60 * This function takes a pack block of arguments from the NAL API
61 * module and passes them to the NAL CB module. The CB module unpacks
62 * the args and calls the appropriate function indicated by index.
63 * Typically this function is used to pass args between kernel and use
65 * As lgmanl exists entirely in kernel, just pass the arg block directly
66 * to the NAL CB, buy passing the args to lib_dispatch
69 * int index the api function that initiated this call
70 * void *args packed block of function args
71 * size_t arg_len length of args block
72 * void *ret A return value for the API NAL
73 * size_t ret_len Size of the return value
78 gmnal_api_forward(nal_t *nal, int index, void *args, size_t arg_len,
79 void *ret, size_t ret_len)
82 nal_cb_t *nal_cb = NULL;
83 gmnal_data_t *nal_data = NULL;
89 if (!nal || !args || (index < 0) || (arg_len < 0)) {
90 CDEBUG(D_ERROR, "Bad args to gmnal_api_forward\n");
94 if (ret && (ret_len <= 0)) {
95 CDEBUG(D_ERROR, "Bad args to gmnal_api_forward\n");
100 if (!nal->nal_data) {
101 CDEBUG(D_ERROR, "bad nal, no nal data\n");
105 nal_data = nal->nal_data;
106 CDEBUG(D_INFO, "nal_data is [%p]\n", nal_data);
108 if (!nal_data->nal_cb) {
109 CDEBUG(D_ERROR, "bad nal_data, no nal_cb\n");
113 nal_cb = nal_data->nal_cb;
114 CDEBUG(D_INFO, "nal_cb is [%p]\n", nal_cb);
116 CDEBUG(D_PORTALS, "gmnal_api_forward calling lib_dispatch\n");
117 lib_dispatch(nal_cb, NULL, index, args, ret);
118 CDEBUG(D_PORTALS, "gmnal_api_forward returns from lib_dispatch\n");
126 * nal_refct == 0 => called on last matching PtlNIFini()
127 * Close down this interface and free any resources associated with it
128 * nal_t nal our nal to shutdown
131 gmnal_api_shutdown(nal_t *nal, int interface)
133 gmnal_data_t *nal_data;
136 if (nal->nal_refct != 0)
139 CDEBUG(D_TRACE, "gmnal_api_shutdown: nal_data [%p]\n", nal_data);
141 LASSERT(nal == global_nal_data->nal);
142 nal_data = nal->nal_data;
143 LASSERT(nal_data == global_nal_data);
144 nal_cb = nal_data->nal_cb;
146 /* Stop portals calling our ioctl handler */
147 libcfs_nal_cmd_unregister(GMNAL);
149 /* XXX for shutdown "under fire" we probably need to set a shutdown
150 * flag so when lib calls us we fail immediately and dont queue any
151 * more work but our threads can still call into lib OK. THEN
152 * shutdown our threads, THEN lib_fini() */
155 gmnal_stop_rxthread(nal_data);
156 gmnal_stop_ctthread(nal_data);
157 gmnal_free_txd(nal_data);
158 gmnal_free_srxd(nal_data);
159 GMNAL_GM_LOCK(nal_data);
160 gm_close(nal_data->gm_port);
162 GMNAL_GM_UNLOCK(nal_data);
163 if (nal_data->sysctl)
164 unregister_sysctl_table (nal_data->sysctl);
165 PORTAL_FREE(nal, sizeof(nal_t));
166 PORTAL_FREE(nal_data, sizeof(gmnal_data_t));
167 PORTAL_FREE(nal_cb, sizeof(nal_cb_t));
169 global_nal_data = NULL;
176 * validate a user address for use in communications
177 * There's nothing to be done here
180 gmnal_api_validate(nal_t *nal, void *base, size_t extent)
190 * Give up the processor
193 gmnal_api_yield(nal_t *nal, unsigned long *flags, int milliseconds)
195 CDEBUG(D_TRACE, "gmnal_api_yield : nal [%p]\n", nal);
197 if (milliseconds != 0) {
198 CERROR("Blocking yield not implemented yet\n");
210 * Take a threadsafe lock
213 gmnal_api_lock(nal_t *nal, unsigned long *flags)
216 gmnal_data_t *nal_data;
219 nal_data = nal->nal_data;
220 nal_cb = nal_data->nal_cb;
222 nal_cb->cb_cli(nal_cb, flags);
229 * Release a threadsafe lock
232 gmnal_api_unlock(nal_t *nal, unsigned long *flags)
234 gmnal_data_t *nal_data;
237 nal_data = nal->nal_data;
238 nal_cb = nal_data->nal_cb;
240 nal_cb->cb_sti(nal_cb, flags);
247 gmnal_api_startup(nal_t *nal, ptl_pid_t requested_pid,
248 ptl_ni_limits_t *requested_limits,
249 ptl_ni_limits_t *actual_limits)
252 nal_cb_t *nal_cb = NULL;
253 gmnal_data_t *nal_data = NULL;
254 gmnal_srxd_t *srxd = NULL;
255 gm_status_t gm_status;
256 unsigned int local_nid = 0, global_nid = 0;
257 ptl_process_id_t process_id;
259 if (nal->nal_refct != 0) {
260 if (actual_limits != NULL) {
261 nal_data = (gmnal_data_t *)nal->nal_data;
262 nal_cb = nal_data->nal_cb;
263 *actual_limits = nal->_cb->ni.actual_limits;
267 /* Called on first PtlNIInit() */
269 CDEBUG(D_TRACE, "startup\n");
271 LASSERT(global_nal_data == NULL);
273 PORTAL_ALLOC(nal_data, sizeof(gmnal_data_t));
275 CDEBUG(D_ERROR, "can't get memory\n");
276 return(PTL_NO_SPACE);
278 memset(nal_data, 0, sizeof(gmnal_data_t));
280 * set the small message buffer size
283 CDEBUG(D_INFO, "Allocd and reset nal_data[%p]\n", nal_data);
284 CDEBUG(D_INFO, "small_msg_size is [%d]\n", nal_data->small_msg_size);
286 PORTAL_ALLOC(nal_cb, sizeof(nal_cb_t));
288 PORTAL_FREE(nal_data, sizeof(gmnal_data_t));
289 return(PTL_NO_SPACE);
291 memset(nal_cb, 0, sizeof(nal_cb_t));
292 CDEBUG(D_INFO, "Allocd and reset nal_cb[%p]\n", nal_cb);
294 GMNAL_INIT_NAL_CB(nal_cb);
296 * String them all together
298 nal->nal_data = (void*)nal_data;
299 nal_cb->nal_data = (void*)nal_data;
301 nal_data->nal_cb = nal_cb;
303 GMNAL_CB_LOCK_INIT(nal_data);
304 GMNAL_GM_LOCK_INIT(nal_data);
308 * initialise the interface,
310 CDEBUG(D_INFO, "Calling gm_init\n");
311 if (gm_init() != GM_SUCCESS) {
312 CDEBUG(D_ERROR, "call to gm_init failed\n");
313 PORTAL_FREE(nal_data, sizeof(gmnal_data_t));
314 PORTAL_FREE(nal_cb, sizeof(nal_cb_t));
319 CDEBUG(D_NET, "Calling gm_open with interface [%d], port [%d], "
320 "name [%s], version [%d]\n", interface, GMNAL_GM_PORT,
321 "gmnal", GM_API_VERSION);
323 GMNAL_GM_LOCK(nal_data);
324 gm_status = gm_open(&nal_data->gm_port, 0, GMNAL_GM_PORT, "gmnal",
326 GMNAL_GM_UNLOCK(nal_data);
328 CDEBUG(D_INFO, "gm_open returned [%d]\n", gm_status);
329 if (gm_status == GM_SUCCESS) {
330 CDEBUG(D_INFO, "gm_open succeeded port[%p]\n",
334 case(GM_INVALID_PARAMETER):
335 CDEBUG(D_ERROR, "gm_open Failure. Invalid Parameter\n");
338 CDEBUG(D_ERROR, "gm_open Failure. GM Busy\n");
340 case(GM_NO_SUCH_DEVICE):
341 CDEBUG(D_ERROR, "gm_open Failure. No such device\n");
343 case(GM_INCOMPATIBLE_LIB_AND_DRIVER):
344 CDEBUG(D_ERROR, "gm_open Failure. Incompatile lib "
347 case(GM_OUT_OF_MEMORY):
348 CDEBUG(D_ERROR, "gm_open Failure. Out of Memory\n");
351 CDEBUG(D_ERROR, "gm_open Failure. Unknow error "
352 "code [%d]\n", gm_status);
355 GMNAL_GM_LOCK(nal_data);
357 GMNAL_GM_UNLOCK(nal_data);
358 PORTAL_FREE(nal_data, sizeof(gmnal_data_t));
359 PORTAL_FREE(nal_cb, sizeof(nal_cb_t));
364 nal_data->small_msg_size = gmnal_small_msg_size;
365 nal_data->small_msg_gmsize =
366 gm_min_size_for_length(gmnal_small_msg_size);
368 if (gmnal_alloc_srxd(nal_data) != GMNAL_STATUS_OK) {
369 CDEBUG(D_ERROR, "Failed to allocate small rx descriptors\n");
370 gmnal_free_txd(nal_data);
371 GMNAL_GM_LOCK(nal_data);
372 gm_close(nal_data->gm_port);
374 GMNAL_GM_UNLOCK(nal_data);
375 PORTAL_FREE(nal_data, sizeof(gmnal_data_t));
376 PORTAL_FREE(nal_cb, sizeof(nal_cb_t));
382 * Hang out a bunch of small receive buffers
383 * In fact hang them all out
385 while((srxd = gmnal_get_srxd(nal_data, 0))) {
386 CDEBUG(D_NET, "giving [%p] to gm_provide_recvive_buffer\n",
388 GMNAL_GM_LOCK(nal_data);
389 gm_provide_receive_buffer_with_tag(nal_data->gm_port,
390 srxd->buffer, srxd->gmsize,
392 GMNAL_GM_UNLOCK(nal_data);
396 * Allocate pools of small tx buffers and descriptors
398 if (gmnal_alloc_txd(nal_data) != GMNAL_STATUS_OK) {
399 CDEBUG(D_ERROR, "Failed to allocate small tx descriptors\n");
400 GMNAL_GM_LOCK(nal_data);
401 gm_close(nal_data->gm_port);
403 GMNAL_GM_UNLOCK(nal_data);
404 PORTAL_FREE(nal_data, sizeof(gmnal_data_t));
405 PORTAL_FREE(nal_cb, sizeof(nal_cb_t));
409 gmnal_start_kernel_threads(nal_data);
411 while (nal_data->rxthread_flag != GMNAL_RXTHREADS_STARTED) {
413 CDEBUG(D_INFO, "Waiting for receive thread signs of life\n");
416 CDEBUG(D_INFO, "receive thread seems to have started\n");
420 * Initialise the portals library
422 CDEBUG(D_NET, "Getting node id\n");
423 GMNAL_GM_LOCK(nal_data);
424 gm_status = gm_get_node_id(nal_data->gm_port, &local_nid);
425 GMNAL_GM_UNLOCK(nal_data);
426 if (gm_status != GM_SUCCESS) {
427 gmnal_stop_rxthread(nal_data);
428 gmnal_stop_ctthread(nal_data);
429 CDEBUG(D_ERROR, "can't determine node id\n");
430 gmnal_free_txd(nal_data);
431 gmnal_free_srxd(nal_data);
432 GMNAL_GM_LOCK(nal_data);
433 gm_close(nal_data->gm_port);
435 GMNAL_GM_UNLOCK(nal_data);
436 PORTAL_FREE(nal_data, sizeof(gmnal_data_t));
437 PORTAL_FREE(nal_cb, sizeof(nal_cb_t));
440 nal_data->gm_local_nid = local_nid;
441 CDEBUG(D_INFO, "Local node id is [%u]\n", local_nid);
442 GMNAL_GM_LOCK(nal_data);
443 gm_status = gm_node_id_to_global_id(nal_data->gm_port, local_nid,
445 GMNAL_GM_UNLOCK(nal_data);
446 if (gm_status != GM_SUCCESS) {
447 CDEBUG(D_ERROR, "failed to obtain global id\n");
448 gmnal_stop_rxthread(nal_data);
449 gmnal_stop_ctthread(nal_data);
450 gmnal_free_txd(nal_data);
451 gmnal_free_srxd(nal_data);
452 GMNAL_GM_LOCK(nal_data);
453 gm_close(nal_data->gm_port);
455 GMNAL_GM_UNLOCK(nal_data);
456 PORTAL_FREE(nal_data, sizeof(gmnal_data_t));
457 PORTAL_FREE(nal_cb, sizeof(nal_cb_t));
460 CDEBUG(D_INFO, "Global node id is [%u]\n", global_nid);
461 nal_data->gm_global_nid = global_nid;
462 snprintf(global_nid_str, GLOBAL_NID_STR_LEN, "%u", global_nid);
468 process_id.nid = global_nid;
470 CDEBUG(D_INFO, "portals_pid is [%u]\n", process_id.pid);
471 CDEBUG(D_INFO, "portals_nid is ["LPU64"]\n", process_id.nid);
473 CDEBUG(D_PORTALS, "calling lib_init\n");
474 if (lib_init(nal_cb, process_id,
475 requested_limits, actual_limits) != PTL_OK) {
476 CDEBUG(D_ERROR, "lib_init failed\n");
477 gmnal_stop_rxthread(nal_data);
478 gmnal_stop_ctthread(nal_data);
479 gmnal_free_txd(nal_data);
480 gmnal_free_srxd(nal_data);
481 GMNAL_GM_LOCK(nal_data);
482 gm_close(nal_data->gm_port);
484 GMNAL_GM_UNLOCK(nal_data);
485 PORTAL_FREE(nal_data, sizeof(gmnal_data_t));
486 PORTAL_FREE(nal_cb, sizeof(nal_cb_t));
491 if (libcfs_nal_cmd_register(GMNAL, &gmnal_cmd, nal->nal_data) != 0) {
492 CDEBUG(D_INFO, "libcfs_nal_cmd_register failed\n");
494 /* XXX these cleanup cases should be restructured to
495 * minimise duplication... */
498 gmnal_stop_rxthread(nal_data);
499 gmnal_stop_ctthread(nal_data);
500 gmnal_free_txd(nal_data);
501 gmnal_free_srxd(nal_data);
502 GMNAL_GM_LOCK(nal_data);
503 gm_close(nal_data->gm_port);
505 GMNAL_GM_UNLOCK(nal_data);
506 PORTAL_FREE(nal_data, sizeof(gmnal_data_t));
507 PORTAL_FREE(nal_cb, sizeof(nal_cb_t));
511 /* might be better to initialise this at module load rather than in
513 nal_data->sysctl = NULL;
514 nal_data->sysctl = register_sysctl_table (gmnalnal_top_sysctl_table, 0);
517 CDEBUG(D_INFO, "gmnal_init finished\n");
518 global_nal_data = nal->nal_data;
520 /* no unload now until shutdown */
529 * Called when module loaded
535 memset(&the_gm_nal, 0, sizeof(nal_t));
536 CDEBUG(D_INFO, "reset nal[%p]\n", &the_gm_nal);
537 GMNAL_INIT_NAL(&the_gm_nal);
539 rc = ptl_register_nal(GMNAL, &the_gm_nal);
541 CERROR("Can't register GMNAL: %d\n", rc);
549 * Called when module removed
553 gmnal_data_t *nal_data = global_nal_data;
554 nal_t *nal = nal_data->nal;
555 nal_cb_t *nal_cb = nal_data->nal_cb;
557 CDEBUG(D_TRACE, "gmnal_fini\n");
559 LASSERT(global_nal_data == NULL);
561 ptl_unregister_nal(GMNAL);