00001
00002
00003
00004
00005
00006
00007
00013 #include <stdio.h>
00014 #include <stdlib.h>
00015 #include <signal.h>
00016 #include <string.h>
00017 #ifndef WIN32
00018 #include <sys/time.h>
00019 #include <unistd.h>
00020 #endif
00021
00022 #include "vipl_priv.h"
00023
00024 #ifndef WIN32
00025
00026 extern const char *_gm_version;
00027 #endif
00028
00070 VIP_ENTRY_POINT VIP_RETURN
00071 VipOpenNic (const VIP_CHAR * DeviceName, VIP_NIC_HANDLE * NicHandle)
00072 {
00073 VIP_NIC *vip_nic_ptr = NULL;
00074 VIP_GM *vip_gm_ptr = NULL;
00075 VIP_UINT16 gm_board_id, gm_port_id;
00076 VIP_UINT32 i;
00077 VIP_RETURN vip_status;
00078 struct timeval current_time;
00079 gm_status_t gm_status = GM_FAILURE;
00080 VIP_DEBUG_LABEL (("VipOpenNic"));
00081
00082 if (DeviceName == NULL)
00083 {
00084 VIP_DEBUG (("DeviceName is null"));
00085 return VIP_INVALID_PARAMETER;
00086 }
00087
00088 if (NicHandle == NULL)
00089 {
00090 VIP_DEBUG (("NicHandle is null"));
00091 return VIP_INVALID_PARAMETER;
00092 }
00093
00094 #ifndef WIN32
00095
00096 if (strncmp (_gm_version, "1.5", 3) > 0)
00097 {
00098 goto gm_version_ok;
00099 }
00100 else
00101 {
00102 if (strncmp (_gm_version, "1.5", 3) < 0)
00103 {
00104 fprintf(stderr, "VI-GM: Invalid GM version (minimum 1.5.1, "
00105 "current is %s\n", _gm_version);
00106 return VIP_ERROR_RESOURCE;
00107 }
00108 else
00109 {
00110 if (_gm_version[3] != '.')
00111 {
00112 fprintf(stderr, "VI-GM: Invalid GM version (minimum 1.5.1, "
00113 "current is %s\n", _gm_version);
00114 return VIP_ERROR_RESOURCE;
00115 }
00116 else
00117 {
00118 goto gm_version_ok;
00119 }
00120 }
00121 }
00122 #endif
00123
00124 gm_version_ok:
00125
00126
00127 if (sscanf (DeviceName, "VINIC%hd", &gm_board_id) != 1)
00128 {
00129 if (strcmp ("VINIC", DeviceName) == 0)
00130 {
00131 gm_board_id = 0;
00132 }
00133 else
00134 {
00135 VIP_DEBUG (("Invalid DeviceName (%s)", DeviceName));
00136 return VIP_INVALID_PARAMETER;
00137 }
00138 }
00139
00140
00141 if (gm_board_id >= VI_GM_MAX_NICS)
00142 {
00143 VIP_DEBUG (("Invalid NIC %d (only %d NICs supported)",
00144 gm_board_id, VI_GM_MAX_NICS));
00145 return VIP_INVALID_PARAMETER;
00146 }
00147
00148 VIP_MUTEX_LOCK (&vip_glob_lock);
00149
00150
00151 if (vip_glob_gm_ptrs[gm_board_id] == NULL)
00152 {
00153 VIP_DEBUG (("No previously initialized GM port"));
00154
00155
00156 vip_gm_ptr = (VIP_GM *) calloc (1, sizeof (VIP_GM));
00157 if (vip_gm_ptr == NULL)
00158 {
00159 VIP_DEBUG (("VIP_GM struct alloc failed"));
00160 goto out_with_vip_gm_lock;
00161 }
00162 vip_glob_gm_ptrs[gm_board_id] = vip_gm_ptr;
00163
00164
00165 gm_port_id = 2;
00166 while (gm_port_id <= VI_GM_MAX_PORTS)
00167 {
00168 if (gm_port_id == VI_GM_PORT_CONN_MANAGER)
00169 {
00170 gm_port_id++;
00171 continue;
00172 }
00173
00174 gm_status = gm_open (&(vip_gm_ptr->gm_port),
00175 gm_board_id, gm_port_id,
00176 "VI-GM over GM", GM_API_VERSION_1_6);
00177 if (gm_status == GM_SUCCESS)
00178 {
00179 break;
00180 }
00181 gm_port_id++;
00182 }
00183
00184 if (gm_status != GM_SUCCESS)
00185 {
00186 VIP_DEBUG (("Unable to open any GM ports on the Myrinet board %d",
00187 gm_board_id));
00188 goto out_with_gm_ptr;
00189 }
00190
00191 gm_set_enable_nack_down (vip_gm_ptr->gm_port, 1);
00192
00193
00194 gm_status = gm_allow_remote_memory_access (vip_gm_ptr->gm_port);
00195 if (gm_status != GM_SUCCESS)
00196 {
00197 VIP_DEBUG_GM (("gm_allow_remote_memory_access() failed"));
00198 goto out_with_gm_port;
00199 }
00200
00201
00202 gm_status = gm_get_node_id (vip_gm_ptr->gm_port, &(vip_gm_ptr->gm_id));
00203 if (gm_status != GM_SUCCESS)
00204 {
00205 VIP_DEBUG_GM (("Unable to get the GM id of the GM port %d "
00206 "of the board %d", gm_port_id, gm_board_id));
00207 goto out_with_gm_port;
00208 }
00209
00210
00211 gm_status = gm_get_unique_board_id (vip_gm_ptr->gm_port,
00212 vip_gm_ptr->mac_address);
00213 if (gm_status != GM_SUCCESS)
00214 {
00215 VIP_DEBUG_GM (("Unable to get the MAC address of the "
00216 "Myrinet board %d", gm_board_id));
00217 goto out_with_gm_port;
00218 }
00219
00220
00221 if (gm_board_id == 0)
00222 {
00223 vip_gm_ptr->conn_mgr_gm_id = vip_gm_ptr->gm_id;
00224 }
00225 else
00226 {
00227 VIP_UCHAR name[GM_MAX_HOST_NAME_LEN];
00228
00229 gm_status = gm_get_host_name (vip_gm_ptr->gm_port, name);
00230 if (gm_status != GM_SUCCESS)
00231 {
00232 VIP_DEBUG_GM (("Unable to get the GM host name of "
00233 "the Myrinet board %d", gm_board_id));
00234 goto out_with_gm_port;
00235 }
00236
00237 *strchr (name, ':') = '\0';
00238 vip_gm_ptr->conn_mgr_gm_id =
00239 gm_host_name_to_node_id (vip_gm_ptr->gm_port, name);
00240 if (vip_gm_ptr->conn_mgr_gm_id == GM_NO_SUCH_NODE_ID)
00241 {
00242 VIP_DEBUG (("Unable to get the GM id of the Myrinet board 0"));
00243 goto out_with_gm_port;
00244 }
00245 }
00246
00247
00248 vip_gm_ptr->max_recv_tokens =
00249 gm_num_receive_tokens (vip_gm_ptr->gm_port);
00250 vip_gm_ptr->recv_tokens = vip_gm_ptr->max_recv_tokens;
00251 vip_gm_ptr->recv_buffers =
00252 (VIP_PVOID **) calloc (vip_gm_ptr->max_recv_tokens,
00253 sizeof (VIP_PVOID *));
00254 if (vip_gm_ptr->recv_buffers == NULL)
00255 {
00256 VIP_DEBUG (("Error allocating GM recv buffers array"));
00257 goto out_with_gm_port;
00258 }
00259
00260 for (i = 0; i < vip_gm_ptr->max_recv_tokens; i++)
00261 {
00262 vip_gm_ptr->recv_buffers[i] =
00263 (VIP_PVOID *) gm_dma_malloc (vip_gm_ptr->gm_port,
00264 VI_GM_EAGER_LENGTH);
00265 if (vip_gm_ptr->recv_buffers[i] == NULL)
00266 {
00267 VIP_DEBUG (("Error allocating GM receive buffer"));
00268 goto out_with_recv_bufs;
00269 }
00270 gm_provide_receive_buffer_with_tag (vip_gm_ptr->gm_port,
00271 vip_gm_ptr->recv_buffers[i],
00272 VI_GM_CTRL_GM_SIZE,
00273 GM_LOW_PRIORITY, i + 1);
00274 vip_gm_ptr->recv_tokens--;
00275 }
00276
00277
00278 vip_gm_ptr->max_send_tokens = gm_num_send_tokens (vip_gm_ptr->gm_port);
00279 vip_gm_ptr->max_send_tokens--;
00280 vip_gm_ptr->send_tokens = vip_gm_ptr->max_send_tokens;
00281 vip_gm_ptr->send_buffers_free = NULL;
00282
00283 vip_gm_ptr->vip_send_req_lookaside
00284 = gm_create_lookaside (sizeof (VIP_SEND_REQ), VI_GM_NUMBER_SEND_BUF);
00285
00286 if (vip_gm_ptr->vip_send_req_lookaside == NULL)
00287 {
00288 VIP_DEBUG (("Error allocating send buffer lookaside"));
00289 goto out_with_recv_bufs;
00290 }
00291
00292 vip_gm_ptr->send_buffers =
00293 (VIP_PVOID **) calloc (VI_GM_NUMBER_SEND_BUF, sizeof (VIP_PVOID *));
00294 if (vip_gm_ptr->send_buffers == NULL)
00295 {
00296 VIP_DEBUG (("Error allocating GM send buffers array"));
00297 goto out_with_send_lookaside;
00298 }
00299
00300 for (i = 0; i < VI_GM_NUMBER_SEND_BUF; i++)
00301 {
00302 vip_gm_ptr->send_buffers[i] =
00303 (VIP_PVOID *) gm_dma_malloc (vip_gm_ptr->gm_port,
00304 VI_GM_EAGER_LENGTH);
00305 if (vip_gm_ptr->send_buffers[i] == NULL)
00306 {
00307 VIP_DEBUG (("Error allocating GM receive buffer"));
00308 goto out_with_send_bufs;
00309 }
00310
00311 if (i == 0)
00312 {
00313 *(vip_gm_ptr->send_buffers[0]) = NULL;
00314 }
00315 else
00316 {
00317 *(vip_gm_ptr->send_buffers[i]) =
00318 vip_gm_ptr->send_buffers[i - 1];
00319 }
00320 }
00321 vip_gm_ptr->send_buffers_free = vip_gm_ptr->send_buffers[i - 1];
00322
00323
00324 vip_gm_ptr->alive_buffer = (VIP_PACKET_ALIVE *)
00325 gm_dma_malloc (vip_gm_ptr->gm_port, sizeof (VIP_PACKET_ALIVE));
00326 if (vip_gm_ptr->alive_buffer == NULL)
00327 {
00328 VIP_DEBUG (("Error allocating alive buffer"));
00329 goto out_with_send_bufs;
00330 }
00331 vip_gm_ptr->alive_buffer->net_srv_magic = VIP_HTON_UINT32 (0);
00332 gm_initialize_alarm (&(vip_gm_ptr->alive_alarm));
00333
00334
00335 VIP_AVL_TREE_INIT (vip_gm_ptr->regmem_avl_tree);
00336 vip_gm_ptr->regmem_avl_lookaside =
00337 gm_create_lookaside (sizeof (VIP_AVL_RANGE), VI_GM_INITIAL_AVL);
00338 if (vip_gm_ptr->regmem_avl_lookaside == NULL)
00339 {
00340 VIP_DEBUG (("Error allocating regmem AVL lookaside list"));
00341 goto out_with_alive_alarm;
00342 }
00343
00344
00345 vip_gm_ptr->notify_lookaside =
00346 gm_create_lookaside (sizeof (VIP_NOTIFY), VI_GM_INITIAL_NOTIFY);
00347 if (vip_gm_ptr->notify_lookaside == NULL)
00348 {
00349 VIP_DEBUG (("Error allocating notify handler lookaside list"));
00350 goto out_with_avl_tree;;
00351 }
00352
00353
00354 vip_gm_ptr->send_fifo_head = NULL;
00355 vip_gm_ptr->send_fifo_tail = NULL;
00356 vip_gm_ptr->send_fifo_queued = 0;
00357
00358
00359 vip_gm_ptr->memory_registered = 0;
00360 vip_gm_ptr->send_buf_free_cnt = VI_GM_NUMBER_SEND_BUF;
00361 vip_gm_ptr->ref_count = 0;
00362 vip_gm_ptr->gm_board_id = gm_board_id;
00363 vip_gm_ptr->gm_port_id = gm_port_id;
00364 vip_gettimeofday (¤t_time, NULL);
00365 gm_srand ((VIP_UINT32) (current_time.tv_sec * current_time.tv_usec));
00366 vip_gm_ptr->magic = gm_rand () * gm_rand ();
00367 vip_gm_ptr->head_waiting_conn_ptr = NULL;
00368 vip_gm_ptr->tail_waiting_conn_ptr = NULL;
00369 vip_gm_ptr->periodic_plumber_cancelled = VIP_FALSE;
00370 vip_gm_ptr->blocking_plumber_cancelled = VIP_FALSE;
00371 gm_bzero (vip_gm_ptr->vip_nic_ptrs,
00372 (VI_GM_MAX_NIC_HANDLES + 1) * sizeof (VIP_NIC *));
00373
00374
00375 VIP_MUTEX_INIT (&(vip_gm_ptr->lock));
00376 VIP_MUTEX_INIT (&(vip_gm_ptr->recv_lock));
00377 VIP_MUTEX_LOCK (&(vip_gm_ptr->lock));
00378
00379
00380 VIP_SEMAPHORE_INIT (&(vip_gm_ptr->blocking_plumber_tokens), 0);
00381
00382
00383 if (VIP_THREAD_CREATE (&(vip_gm_ptr->plumber_periodic),
00384 vip_plumber_periodic, vip_gm_ptr) != 0)
00385 {
00386 VIP_DEBUG (("Unable to spawn plumber periodic thread"));
00387 goto out_with_notify_lookaside;
00388 }
00389
00390
00391 if (VIP_THREAD_CREATE (&(vip_gm_ptr->plumber_blocking),
00392 vip_plumber_blocking, vip_gm_ptr) != 0)
00393 {
00394 VIP_DEBUG (("Unable to spawn plumber blocking thread"));
00395 goto out_with_periodic_plumber;
00396 }
00397 }
00398 else
00399 {
00400 vip_gm_ptr = vip_glob_gm_ptrs[gm_board_id];
00401 VIP_MUTEX_LOCK (&(vip_gm_ptr->lock));
00402 }
00403
00404
00405 if (vip_gm_ptr->ref_count >= VI_GM_MAX_NIC_HANDLES)
00406 {
00407 VIP_ASSERT (vip_gm_ptr->ref_count == VI_GM_MAX_NIC_HANDLES);
00408 VIP_DEBUG (("NIC handles limit reached"));
00409 goto out_with_blocking_plumber;
00410 }
00411
00412
00413 if (vip_glob_nic_lookaside == NULL)
00414 {
00415 vip_glob_nic_lookaside = gm_create_lookaside (sizeof (VIP_NIC), 1);
00416 if (vip_glob_nic_lookaside == NULL)
00417 {
00418 VIP_DEBUG (("Unable to initialize NIC lookaside list"));
00419 goto out_with_blocking_plumber;
00420 }
00421 }
00422
00423
00424 vip_nic_ptr = (VIP_NIC *) gm_lookaside_zalloc (vip_glob_nic_lookaside);
00425 if (vip_nic_ptr == NULL)
00426 {
00427 VIP_DEBUG (("VIP_NIC lookaside alloc failed"));
00428 goto out_with_blocking_plumber;
00429 }
00430
00431
00432 vip_status = vip_init_handle_set (&(vip_nic_ptr->vip_vi_set),
00433 sizeof (VIP_VI),
00434 VI_GM_MAX_VI, VIP_VI_MAGIC);
00435 if (vip_status != VIP_SUCCESS)
00436 {
00437 VIP_DEBUG (("VI handle set init failed"));
00438 goto out_with_nic_ptr;
00439 }
00440 vip_nic_ptr->vip_vi_set.vip_nic_ptr = vip_nic_ptr;
00441
00442 vip_status = vip_init_handle_set (&(vip_nic_ptr->vip_mem_set),
00443 sizeof (VIP_MEM),
00444 VI_GM_MAX_REGISTER_REGIONS,
00445 VIP_MEM_MAGIC);
00446 if (vip_status != VIP_SUCCESS)
00447 {
00448 VIP_DEBUG (("REGMEM handle set init failed"));
00449 goto out_with_vi_set;
00450 }
00451 vip_nic_ptr->vip_mem_set.vip_nic_ptr = vip_nic_ptr;
00452
00453 vip_status = vip_init_handle_set (&(vip_nic_ptr->vip_ptag_set),
00454 sizeof (VIP_PTAG),
00455 VI_GM_MAX_PTAGS, VIP_PTAG_MAGIC);
00456 if (vip_status != VIP_SUCCESS)
00457 {
00458 VIP_DEBUG (("PTAG handle set init failed"));
00459 goto out_with_mem_set;
00460 }
00461 vip_nic_ptr->vip_ptag_set.vip_nic_ptr = vip_nic_ptr;
00462
00463 vip_status = vip_init_handle_set (&(vip_nic_ptr->vip_cq_set),
00464 sizeof (VIP_CQ),
00465 VI_GM_MAX_CQ, VIP_CQ_MAGIC);
00466 if (vip_status != VIP_SUCCESS)
00467 {
00468 VIP_DEBUG (("CQ handle set init failed"));
00469 goto out_with_ptag_set;
00470 }
00471 vip_nic_ptr->vip_cq_set.vip_nic_ptr = vip_nic_ptr;
00472
00473 vip_status = vip_init_handle_set (&(vip_nic_ptr->vip_conn_set),
00474 sizeof (VIP_CONN),
00475 VI_GM_MAX_CONN, VIP_CONN_MAGIC);
00476 if (vip_status != VIP_SUCCESS)
00477 {
00478 VIP_DEBUG (("CONN handle set init failed"));
00479 goto out_with_cq_set;
00480 }
00481 vip_nic_ptr->vip_conn_set.vip_nic_ptr = vip_nic_ptr;
00482
00483
00484 vip_nic_ptr->vip_mem_handle_free = 1;
00485 vip_nic_ptr->vip_mem_handle_ptrs[0] = NULL;
00486 for (i = 1; i <= VI_GM_MAX_REGISTER_REGIONS; i++)
00487 {
00488 vip_nic_ptr->vip_mem_handle_ptrs[i] =
00489 (VIP_MEM *) ((VIP_UINTPTR) (i + 1));
00490 }
00491 vip_nic_ptr->vip_mem_handle_ptrs[VI_GM_MAX_REGISTER_REGIONS] = NULL;
00492
00493
00494 vip_nic_ptr->vip_vi_index_free = 1;
00495 vip_nic_ptr->vip_vi_ptrs[0] = NULL;
00496 for (i = 1; i <= VI_GM_MAX_VI; i++)
00497 {
00498 vip_nic_ptr->vip_vi_ptrs[i] = (VIP_VI *) ((VIP_UINTPTR) (i + 1));
00499 }
00500 vip_nic_ptr->vip_vi_ptrs[VI_GM_MAX_VI] = NULL;
00501
00502
00503 vip_nic_ptr->magic = VIP_NIC_MAGIC;
00504 vip_nic_ptr->ptag_last_id = 1;
00505 vip_nic_ptr->error_callback = vip_default_error_callback;
00506 vip_nic_ptr->error_callback_context = NULL;
00507 VIP_MUTEX_INIT (&(vip_nic_ptr->lock));
00508 vip_nic_ptr->ns_initialized = VIP_FALSE;
00509
00510
00511 vip_nic_ptr->vip_gm_ptr = vip_gm_ptr;
00512 vip_gm_ptr->ref_count++;
00513 for (i = 1; i <= VI_GM_MAX_NIC_HANDLES; i++)
00514 {
00515 if (vip_gm_ptr->vip_nic_ptrs[i] == NULL)
00516 {
00517 vip_gm_ptr->vip_nic_ptrs[i] = vip_nic_ptr;
00518 vip_nic_ptr->index = i;
00519
00520 *NicHandle = (VIP_NIC_HANDLE) vip_nic_ptr;
00521 if (vip_gm_ptr->ref_count == 1)
00522 {
00523
00524 vip_alive_alarm_callback (vip_gm_ptr);
00525 }
00526
00527 VIP_MUTEX_UNLOCK (&(vip_gm_ptr->lock));
00528 VIP_MUTEX_UNLOCK (&vip_glob_lock);
00529 VIP_DEBUG (("Success"));
00530 return VIP_SUCCESS;
00531 }
00532 }
00533
00534 out_with_cq_set:
00535 vip_destroy_cq_handle_set (&(vip_nic_ptr->vip_cq_set));
00536 out_with_ptag_set:
00537 vip_destroy_ptag_handle_set (&(vip_nic_ptr->vip_ptag_set));
00538 out_with_mem_set:
00539 vip_destroy_mem_handle_set (&(vip_nic_ptr->vip_mem_set));
00540 out_with_vi_set:
00541 vip_destroy_vi_handle_set (&(vip_nic_ptr->vip_vi_set));
00542 out_with_nic_ptr:
00543 gm_lookaside_free (vip_nic_ptr);
00544
00545 out_with_blocking_plumber:
00546 if (vip_gm_ptr->ref_count == 0)
00547 {
00548 vip_gm_ptr->blocking_plumber_cancelled = VIP_TRUE;
00549 VIP_SEMAPHORE_POST (&(vip_gm_ptr->blocking_plumber_tokens));
00550 VIP_THREAD_JOIN (vip_gm_ptr->plumber_blocking);
00551 }
00552 else
00553 {
00554
00555 VIP_MUTEX_UNLOCK (&(vip_gm_ptr->lock));
00556 VIP_MUTEX_UNLOCK (&vip_glob_lock);
00557 return VIP_ERROR_RESOURCE;
00558 }
00559
00560 out_with_periodic_plumber:
00561 vip_gm_ptr->periodic_plumber_cancelled = VIP_TRUE;
00562 VIP_THREAD_JOIN (vip_gm_ptr->plumber_periodic);
00563
00564 out_with_notify_lookaside:
00565 VIP_SEMAPHORE_DESTROY (&(vip_gm_ptr->blocking_plumber_tokens));
00566 VIP_MUTEX_UNLOCK (&(vip_gm_ptr->lock));
00567 VIP_MUTEX_DESTROY (&(vip_gm_ptr->lock));
00568 gm_destroy_lookaside (vip_gm_ptr->notify_lookaside);
00569
00570 out_with_avl_tree:
00571 VIP_AVL_TREE_DESTROY (vip_gm_ptr->regmem_avl_tree);
00572 gm_destroy_lookaside (vip_gm_ptr->regmem_avl_lookaside);
00573
00574 out_with_alive_alarm:
00575 gm_cancel_alarm (&(vip_gm_ptr->alive_alarm));
00576 gm_dma_free (vip_gm_ptr->gm_port, vip_gm_ptr->alive_buffer);
00577
00578 out_with_send_bufs:
00579 for (i = 0; i < VI_GM_NUMBER_SEND_BUF; i++)
00580 {
00581 if (vip_gm_ptr->send_buffers[i] != NULL)
00582 {
00583 gm_dma_free (vip_gm_ptr->gm_port, vip_gm_ptr->send_buffers[i]);
00584 }
00585 }
00586 free (vip_gm_ptr->send_buffers);
00587
00588 out_with_send_lookaside:
00589 gm_destroy_lookaside (vip_gm_ptr->vip_send_req_lookaside);
00590
00591 out_with_recv_bufs:
00592 for (i = 0; i < vip_gm_ptr->max_recv_tokens; i++)
00593 {
00594 if (vip_gm_ptr->recv_buffers[i] != NULL)
00595 {
00596 gm_dma_free (vip_gm_ptr->gm_port, vip_gm_ptr->recv_buffers[i]);
00597 }
00598 }
00599 free (vip_gm_ptr->recv_buffers);
00600
00601 out_with_gm_port:
00602 gm_close (vip_gm_ptr->gm_port);
00603 out_with_gm_ptr:
00604 free (vip_gm_ptr);
00605 vip_glob_gm_ptrs[gm_board_id] = NULL;
00606 out_with_vip_gm_lock:
00607 VIP_MUTEX_UNLOCK (&vip_glob_lock);
00608
00609 return VIP_ERROR_RESOURCE;
00610 }