00001
00002
00003
00004
00005
00006
00007
00015 #ifndef WIN32
00016 #include <unistd.h>
00017 #include <sys/time.h>
00018 #include <syslog.h>
00019 #else
00020 #include <sys/timeb.h>
00021 #endif
00022 #include <stdarg.h>
00023 #include <string.h>
00024 #include <stdlib.h>
00025
00026 #include "vipl_priv.h"
00027
00028
00030 VIP_MUTEX_ATTR;
00031
00032 #ifndef WIN32
00033
00036 VIP_MUTEX_T vip_glob_lock = PTHREAD_MUTEX_INITIALIZER;
00040 VIP_MUTEX_T vip_gm_host_name_lock = PTHREAD_MUTEX_INITIALIZER;
00041 #else
00042 VIP_MUTEX_T vip_glob_lock;
00043 VIP_MUTEX_T vip_gm_host_name_lock;
00044 #endif
00045
00047 struct gm_lookaside *vip_glob_nic_lookaside = NULL;
00048
00050 VIP_GM *vip_glob_gm_ptrs[VI_GM_MAX_NICS] = { 0 };
00051
00052
00053
00054
00055
00056
00057
00058
00074 VIP_UINT64
00075 vip_addr2addrbits (VIP_PVOID Address)
00076 {
00077 VIP_PVOID64 p;
00078
00079 p.AddressBits = 0;
00080 p.Address = Address;
00081 return p.AddressBits;
00082 }
00083
00098 VIP_PVOID
00099 vip_addrbits2addr (VIP_UINT64 AddressBits)
00100 {
00101 VIP_PVOID64 p;
00102
00103 p.AddressBits = AddressBits;
00104 return p.Address;
00105 }
00106
00117 VIP_ENTRY_POINT void
00118 vip_millisleep (unsigned int milliseconds)
00119 {
00120 #ifndef WIN32
00121 usleep (milliseconds * 1000);
00122 #else
00123 Sleep (milliseconds);
00124 #endif
00125 }
00126
00141 VIP_ENTRY_POINT int
00142 vip_gettimeofday (struct timeval *tv, void *p)
00143 {
00144 #ifndef WIN32
00145 return gettimeofday (tv, p);
00146 #else
00147 struct _timeb tb;
00148
00149 _ftime (&tb);
00150 if (tv != NULL) {
00151 tv->tv_sec = tb.time;
00152 tv->tv_usec = tb.millitm * 1000;
00153 }
00154 return 0;
00155 #endif
00156 }
00157
00172 VIP_ENTRY_POINT int
00173 vip_gethostname (char *name, size_t len)
00174 {
00175 #ifndef WIN32
00176 return gethostname (name, len);
00177 #else
00178 strcpy (name, "hostname");
00179 return 0;
00180 #endif
00181 }
00182
00183
00184
00185
00186
00187
00188
00189
00201 VIP_ENTRY_POINT void
00202 vip_notice (char *msg, ...)
00203 {
00204 va_list ap;
00205
00206 va_start (ap, msg);
00207 vfprintf (stderr, msg, ap);
00208 va_end (ap);
00209 }
00210
00222 VIP_ENTRY_POINT char *
00223 vip_vsprintf (const char *msg, ...)
00224 {
00225 char* output;
00226 va_list ap;
00227
00228 va_start (ap, msg);
00229 output = malloc (4096);
00230 if (output != NULL)
00231 {
00232 vsprintf (output, msg, ap);
00233 }
00234 va_end (ap);
00235 return output;
00236 }
00237
00262 void
00263 vip_debug (const char *function_name, const char *file, VIP_UINT32 line,
00264 const char *msg, ...)
00265 {
00266 va_list ap;
00267 char hostname[64];
00268 char fmt[4096];
00269
00270 va_start (ap, msg);
00271 VIP_ASSERT (gethostname (hostname, 64) == 0);
00272 sprintf (fmt, "VI-GM [%s/%lu] <%s>: %s (%s:%d)\n",
00273 hostname, (unsigned long) VIP_THREAD_SELF (),
00274 function_name, msg, file, line);
00275 vfprintf (stderr, fmt, ap);
00276 va_end (ap);
00277 }
00278
00305 void
00306 vip_debug_gm (const char *function_name, const char *file, VIP_UINT32 line,
00307 gm_status_t gm_status, const char *msg, ...)
00308 {
00309 va_list ap;
00310 char fmt[4096];
00311 char output[4096];
00312
00313 va_start (ap, msg);
00314 sprintf (fmt, "VI-GM <%s>: %s (%s:%d)\n", function_name, msg, file, line);
00315 vsprintf (output, fmt, ap);
00316 gm_perror (output, gm_status);
00317 }
00318
00331 void
00332 vi_gm_debug_checksum_compute (VIP_CHKSUM * cksum_ptr,
00333 void *ptr, VIP_UINT32 len)
00334 {
00335 cksum_ptr->sum = gm_crc (ptr, len);
00336 cksum_ptr->len = len;
00337 }
00338
00352 void
00353 vi_gm_debug_checksum_check (VIP_UCHAR * msg, void *buf,
00354 VIP_CHKSUM * chksum_ptr)
00355 {
00356 VIP_CHKSUM chksum_comp;
00357 VIP_DEBUG_LABEL (("vi_gm_debug_checksum_check"));
00358
00359 vi_gm_debug_checksum_compute (&chksum_comp, buf, chksum_ptr->len);
00360 if (chksum_comp.sum != chksum_ptr->sum)
00361 {
00362 VIP_ABORT (("VI-GM checksum error (%s)", msg));
00363 }
00364 }
00365
00379 void
00380 vi_gm_debug_checksum_copy (VIP_CHKSUM * cksum_target,
00381 VIP_CHKSUM * cksum_source)
00382 {
00383 cksum_target->sum = cksum_source->sum;
00384 cksum_target->len = cksum_source->len;
00385 }
00386
00387
00388
00389
00390
00391
00392
00393
00414 VIP_RETURN
00415 vip_wait_for_notification (VIP_ULONG timeout,
00416 VIP_HANDLE * handle_ptr,
00417 VIP_EVENT_T * event_ptr,
00418 VIP_BOOLEAN (*check) (VIP_PVOID),
00419 VIP_PVOID context)
00420 {
00421 struct timespec timeout_abs;
00422 struct timeval time_abs;
00423 double time_now, time_finish;
00424 VIP_GM *vip_gm_ptr;
00425 VIP_NIC *vip_nic_ptr;
00426 VIP_UINT32 return_code;
00427 VIP_DEBUG_LABEL (("vip_wait_for_notification"));
00428
00429 handle_ptr->ref_count++;
00430 vip_nic_ptr = handle_ptr->vip_nic_ptr;
00431 vip_gm_ptr = vip_nic_ptr->vip_gm_ptr;
00432 VIP_ASSERT_MUTEX_LOCKED (&(vip_gm_ptr->lock));
00433
00434 if (timeout == 0)
00435 {
00436 if (check (context) == VIP_FALSE)
00437 {
00438 VIP_DEBUG (("Check is unsuccessfull (timeout 0)"));
00439 handle_ptr->ref_count--;
00440 return VIP_TIMEOUT;
00441 }
00442 }
00443 else
00444 {
00445 VIP_SEMAPHORE_POST (&(vip_gm_ptr->blocking_plumber_tokens));
00446 if (timeout == VIP_INFINITE)
00447 {
00448 while (check (context) == VIP_FALSE)
00449 {
00450 VIP_EVENT_WAIT (event_ptr, &(vip_gm_ptr->lock));
00451 if (vip_nic_ptr->magic != VIP_NIC_MAGIC)
00452 {
00453 VIP_SEMAPHORE_WAIT (&(vip_gm_ptr->blocking_plumber_tokens));
00454 VIP_DEBUG (("NIC has been destroyed during waiting time"));
00455 handle_ptr->ref_count--;
00456 return VIP_INVALID_PARAMETER;
00457 }
00458 }
00459 }
00460 else
00461 {
00462 return_code = vip_gettimeofday (&time_abs, NULL);
00463 VIP_ASSERT (return_code == 0);
00464
00465 time_now = time_abs.tv_sec + (time_abs.tv_usec / 1000000.);
00466 time_finish = time_now + (timeout / 1000.);
00467 timeout_abs.tv_sec = (VIP_ULONG) time_finish;
00468 timeout_abs.tv_nsec = ((time_finish - timeout_abs.tv_sec)
00469 * 1000000000);
00470
00471 while (check (context) == VIP_FALSE)
00472 {
00473 VIP_EVENT_WAIT_TIMEOUT (event_ptr, &(vip_gm_ptr->lock),
00474 &timeout_abs);
00475
00476 if (vip_nic_ptr->magic != VIP_NIC_MAGIC)
00477 {
00478 VIP_SEMAPHORE_WAIT (&(vip_gm_ptr->blocking_plumber_tokens));
00479 VIP_DEBUG (("NIC has been destroyed during waiting time"));
00480 handle_ptr->ref_count--;
00481 return VIP_INVALID_PARAMETER;
00482 }
00483
00484 if (check (context) == VIP_FALSE)
00485 {
00486 return_code = vip_gettimeofday (&time_abs, NULL);
00487 VIP_ASSERT (return_code == 0);
00488
00489 time_now = time_abs.tv_sec + (time_abs.tv_usec / 1000000.);
00490 if (time_now > time_finish)
00491 {
00492 VIP_SEMAPHORE_WAIT (&(vip_gm_ptr->blocking_plumber_tokens));
00493 VIP_DEBUG (("Check is unsuccessfull after timeout"));
00494 handle_ptr->ref_count--;
00495 return VIP_TIMEOUT;
00496 }
00497 }
00498 }
00499 }
00500
00501 VIP_SEMAPHORE_WAIT (&(vip_gm_ptr->blocking_plumber_tokens));
00502 }
00503
00504 VIP_DEBUG (("Success"));
00505 handle_ptr->ref_count--;
00506 return VIP_SUCCESS;
00507 }
00508
00525 void
00526 vip_default_error_callback (VIP_PVOID Context,
00527 VIP_ERROR_DESCRIPTOR * ErrorDesc)
00528 {
00529 char vip_error_msg[2048];
00530 VIP_DEBUG_LABEL (("vip_default_error_callback"));
00531
00532 if (ErrorDesc == NULL)
00533 {
00534 #ifndef WIN32
00535 syslog (LOG_WARNING,
00536 "VI/GM: Error callback called with null error descriptor");
00537 #else
00538 fprintf (stderr,
00539 "VI/GM: Error callback called with null error descriptor\n");
00540 #endif
00541 return;
00542 }
00543
00544 sprintf (vip_error_msg, "VI/GM error callback: Operation = ");
00545 switch ((VIP_UINT32) (ErrorDesc->OpCode))
00546 {
00547 case VIP_STATUS_OP_SEND:
00548 strcat (vip_error_msg, "Send");
00549 break;
00550 case VIP_STATUS_OP_RECEIVE:
00551 strcat (vip_error_msg, "Receive");
00552 break;
00553 case VIP_STATUS_OP_RDMA_WRITE:
00554 strcat (vip_error_msg, "RDMA Write");
00555 break;
00556 case VIP_STATUS_OP_REMOTE_RDMA_WRITE:
00557 strcat (vip_error_msg, "Remote RDMA Write");
00558 break;
00559 case VIP_STATUS_OP_RDMA_READ:
00560 strcat (vip_error_msg, "RDMA Read");
00561 break;
00562 default:
00563 strcat (vip_error_msg, "undefined");
00564 }
00565
00566 strcat (vip_error_msg, ", Ressource = ");
00567 switch (ErrorDesc->ResourceCode)
00568 {
00569 case VIP_RESOURCE_NIC:
00570 strcat (vip_error_msg, "NIC");
00571 break;
00572 case VIP_RESOURCE_VI:
00573 strcat (vip_error_msg, "VI");
00574 break;
00575 case VIP_RESOURCE_CQ:
00576 strcat (vip_error_msg, "CQ");
00577 break;
00578 case VIP_RESOURCE_DESCRIPTOR:
00579 strcat (vip_error_msg, "DESCRIPTOR");
00580 break;
00581 default:
00582 strcat (vip_error_msg, "undefined");
00583 }
00584
00585 strcat (vip_error_msg, ", Error = ");
00586 switch (ErrorDesc->ErrorCode)
00587 {
00588 case VIP_ERROR_POST_DESC:
00589 strcat (vip_error_msg, "\"Post Descriptor Error (A1)\"");
00590 break;
00591 case VIP_ERROR_CONN_LOST:
00592 strcat (vip_error_msg, "\"Connection Lost (A2)\"");
00593 break;
00594 case VIP_ERROR_RECVQ_EMPTY:
00595 strcat (vip_error_msg, "\"Receive Queue Empty (A3)\"");
00596 break;
00597 case VIP_ERROR_VI_OVERRUN:
00598 strcat (vip_error_msg, "\"VI Overrun (A4)\"");
00599 break;
00600 case VIP_ERROR_RDMAW_PROT:
00601 strcat (vip_error_msg, "\"RDMA Write Protection Error (A5)\"");
00602 break;
00603 case VIP_ERROR_RDMAW_DATA:
00604 strcat (vip_error_msg, "\"RDMA Write Data Error (A6)\"");
00605 break;
00606 case VIP_ERROR_RDMAW_ABORT:
00607 strcat (vip_error_msg, "\"RDMA Write Packet Abort (A7)\"");
00608 break;
00609 case VIP_ERROR_RDMAR_PROT:
00610 strcat (vip_error_msg, "\"RDMA Read Protection Error (A8)\"");
00611 break;
00612 case VIP_ERROR_COMP_PROT:
00613 strcat (vip_error_msg, "\"Completion Protection Error (A9)\"");
00614 break;
00615 case VIP_ERROR_RDMA_TRANSPORT:
00616 strcat (vip_error_msg, "\"RDMA Write Transport Error (A10)\"");
00617 break;
00618 case VIP_ERROR_CATASTROPHIC:
00619 strcat (vip_error_msg, "\"Catastrophic Error (A11)\"");
00620 break;
00621 default:
00622 strcat (vip_error_msg, "undefined");
00623 }
00624
00625 VIP_DEBUG (("%s", vip_error_msg));
00626 #ifndef WIN32
00627 syslog (LOG_ERR, vip_error_msg);
00628 #else
00629 fprintf (stderr, "%s\n", vip_error_msg);
00630 #endif
00631 }
00632
00653 void
00654 vip_generate_async_error (VIP_NIC * vip_nic_ptr,
00655 VIP_VI * vip_vi_ptr,
00656 VIP_CQ * vip_cq_ptr,
00657 VIP_DESCRIPTOR * vip_desc_ptr,
00658 VIP_RESOURCE_CODE resource_code,
00659 VIP_ERROR_CODE error_code,
00660 VIP_UINT32 opcode)
00661 {
00662 VIP_ERROR_DESCRIPTOR vip_error_desc;
00663 VIP_DEBUG_LABEL (("vip_generate_async_error"));
00664
00665 VIP_ASSERT (vip_nic_ptr != NULL);
00666 VIP_ASSERT_MUTEX_LOCKED (&(vip_nic_ptr->lock));
00667 VIP_ASSERT_MUTEX_LOCKED (&(vip_nic_ptr->vip_gm_ptr->lock));
00668 vip_error_desc.NicHandle = vip_nic_ptr;
00669 vip_error_desc.ViHandle = vip_vi_ptr;
00670 vip_error_desc.CQHandle = vip_cq_ptr;
00671 vip_error_desc.DescriptorPtr = vip_desc_ptr;
00672
00673 if (opcode != 0)
00674 {
00675 vip_error_desc.OpCode = opcode;
00676 }
00677 else
00678 {
00679 vip_error_desc.OpCode = 0x000F0000;
00680 }
00681
00682 vip_error_desc.ResourceCode = resource_code;
00683 vip_error_desc.ErrorCode = error_code;
00684
00685 VIP_ASSERT (vip_nic_ptr->error_callback != NULL);
00686 VIP_DEBUG (("Generate an asynchronous error"));
00687 vip_nic_ptr->error_callback (vip_nic_ptr->error_callback_context,
00688 &vip_error_desc);
00689
00690 VIP_DEBUG (("Success"));
00691 }
00692
00708 void
00709 vip_notify_desc_completion (VIP_DESCRIPTOR * vip_desc_ptr,
00710 VIP_VI * vip_vi_ptr,
00711 VIP_BOOLEAN recv_queue)
00712 {
00713 VIP_NIC *vip_nic_ptr;
00714 VIP_CQ *vip_cq_ptr;
00715 VIP_CQ_ENTRY *vip_cq_entry_ptr;
00716 VIP_VI_QUEUE *vip_vi_queue_ptr;
00717 VIP_DEBUG_LABEL (("vip_notify_desc_completion"));
00718
00719 vip_nic_ptr = vip_vi_ptr->handle.vip_nic_ptr;
00720 VIP_ASSERT (vip_desc_ptr != NULL);
00721 VIP_ASSERT ((vip_desc_ptr->CS.Status & VIP_STATUS_DONE) == 0);
00722 VIP_ASSERT_MUTEX_LOCKED (&(vip_nic_ptr->lock));
00723 VIP_ASSERT_MUTEX_LOCKED (&(vip_nic_ptr->vip_gm_ptr->lock));
00724
00725 if (recv_queue == VIP_FALSE)
00726 {
00727 vip_vi_queue_ptr = &(vip_vi_ptr->send_queue);
00728 vip_cq_ptr = vip_vi_ptr->send_queue.vip_cq_ptr;
00729 }
00730 else
00731 {
00732 vip_vi_queue_ptr = &(vip_vi_ptr->recv_queue);
00733 vip_cq_ptr = vip_vi_ptr->recv_queue.vip_cq_ptr;
00734 }
00735
00736
00737 VIP_ASSERT (vip_desc_ptr == vip_vi_queue_ptr->current_desc);
00738 if (vip_check_memory_handle (vip_nic_ptr, vip_vi_queue_ptr->current_mem,
00739 (VIP_UINTPTR) vip_desc_ptr,
00740 sizeof (VIP_CONTROL_SEGMENT),
00741 vip_vi_ptr->vip_ptag_ptr->id) != VIP_SUCCESS)
00742 {
00743 VIP_DEBUG (("Control segment Memory Handle check error (comp)"));
00744 vip_generate_async_error
00745 (vip_nic_ptr, vip_vi_ptr, NULL, vip_desc_ptr,
00746 VIP_RESOURCE_DESCRIPTOR, VIP_ERROR_COMP_PROT,
00747 (vip_desc_ptr->CS.Status & VIP_STATUS_OP_MASK));
00748
00749
00750 if (vip_vi_ptr->state != VIP_STATE_ERROR)
00751 {
00752
00753 vip_vi_transition_to_error_state (vip_vi_ptr, VIP_TRUE);
00754
00755
00756 vip_generate_async_error (vip_nic_ptr, vip_vi_ptr, NULL, NULL,
00757 VIP_RESOURCE_VI, VIP_ERROR_CONN_LOST, 0);
00758 }
00759
00760 return;
00761 }
00762
00763 vip_desc_ptr->CS.Status |= VIP_STATUS_DONE;
00764
00765 if (vip_desc_ptr == vip_vi_queue_ptr->first)
00766 {
00767
00768 VIP_DEBUG (("Notify %s completion (desc=%p) to the VI",
00769 ((recv_queue == VIP_FALSE) ? "Send" : "Receive"),
00770 vip_desc_ptr));
00771 if (vip_vi_queue_ptr->event_count > 0)
00772 {
00773 VIP_EVENT_SIGNAL (&(vip_vi_queue_ptr->event));
00774 }
00775 }
00776
00777 if (vip_cq_ptr != NULL)
00778 {
00779
00780 VIP_DEBUG (("Notify completion queue"));
00781 vip_cq_entry_ptr = &(vip_cq_ptr->queue[vip_cq_ptr->next_completion]);
00782 vip_cq_entry_ptr->vip_vi_ptr = vip_vi_ptr;
00783 vip_cq_entry_ptr->recv_queue = recv_queue;
00784 vip_cq_entry_ptr->completed = VIP_TRUE;
00785
00786
00787 if ((vip_cq_ptr->next_completion + 1) < vip_cq_ptr->count)
00788 {
00789 vip_cq_ptr->next_completion++;
00790 }
00791 else
00792 {
00793 vip_cq_ptr->next_completion = 0;
00794 }
00795
00796
00797 if (vip_cq_ptr->event_count > 0)
00798 {
00799 VIP_EVENT_SIGNAL (&(vip_cq_ptr->event));
00800 }
00801 }
00802
00803 VIP_DEBUG (("Success"));
00804 }
00805
00821 void
00822 vip_vi_transition_to_error_state (VIP_VI * vip_vi_ptr,
00823 VIP_BOOLEAN send_conn_lost)
00824 {
00825 VIP_NIC *vip_nic_ptr;
00826 VIP_CQ *vip_cq_ptr;
00827 VIP_CQ_ENTRY *vip_cq_entry_ptr;
00828 VIP_VI_QUEUE *vip_vi_queue_ptr;
00829 VIP_DESCRIPTOR *vip_desc_ptr;
00830 VIP_DEBUG_LABEL (("vip_vi_transition_to_error_state"));
00831
00832 vip_nic_ptr = vip_vi_ptr->handle.vip_nic_ptr;
00833 VIP_ASSERT_MUTEX_LOCKED (&(vip_nic_ptr->lock));
00834 VIP_ASSERT_MUTEX_LOCKED (&(vip_nic_ptr->vip_gm_ptr->lock));
00835 vip_vi_ptr->state = VIP_STATE_ERROR;
00836
00837
00838 vip_vi_queue_ptr = &(vip_vi_ptr->recv_queue);
00839 vip_cq_ptr = vip_vi_ptr->recv_queue.vip_cq_ptr;
00840 vip_desc_ptr = vip_vi_ptr->recv_queue.current_desc;
00841
00842 while (vip_desc_ptr != NULL)
00843 {
00844 if ((vip_desc_ptr->CS.Status & VIP_STATUS_DONE) == 0)
00845 {
00846 vip_desc_ptr->CS.Status |= VIP_STATUS_DESC_FLUSHED_ERROR;
00847 vip_desc_ptr->CS.Status |= VIP_STATUS_DONE;
00848
00849
00850 if ((vip_desc_ptr == vip_vi_queue_ptr->first)
00851 && (vip_vi_queue_ptr->event_count > 0))
00852 {
00853 VIP_EVENT_SIGNAL (&(vip_vi_queue_ptr->event));
00854 }
00855 }
00856
00857 if (vip_cq_ptr != NULL)
00858 {
00859
00860 VIP_DEBUG (("Notify completion queue"));
00861 vip_cq_entry_ptr =
00862 &(vip_cq_ptr->queue[vip_cq_ptr->next_completion]);
00863 vip_cq_entry_ptr->vip_vi_ptr = vip_vi_ptr;
00864 vip_cq_entry_ptr->recv_queue = VIP_TRUE;
00865 vip_cq_entry_ptr->completed = VIP_TRUE;
00866
00867
00868 if ((vip_cq_ptr->next_completion + 1) < vip_cq_ptr->count)
00869 {
00870 vip_cq_ptr->next_completion++;
00871 }
00872 else
00873 {
00874 vip_cq_ptr->next_completion = 0;
00875 }
00876
00877 if (vip_cq_ptr->event_count > 0)
00878 {
00879 VIP_EVENT_SIGNAL (&(vip_cq_ptr->event));
00880 }
00881 }
00882
00883 VIP_ASSERT ((vip_vi_queue_ptr->last != vip_desc_ptr)
00884 || (vip_desc_ptr->CS.Next.Address == NULL));
00885 vip_vi_queue_ptr->current_desc = vip_desc_ptr->CS.Next.Address;
00886 vip_vi_queue_ptr->current_mem = vip_desc_ptr->CS.NextHandle;
00887 vip_desc_ptr = vip_vi_queue_ptr->current_desc;
00888 }
00889 VIP_ASSERT (vip_vi_queue_ptr->current_desc == NULL);
00890 vip_vi_queue_ptr->current_mem = 0;
00891 vip_vi_queue_ptr->count_to_process = 0;
00892
00893
00894 vip_vi_queue_ptr = &(vip_vi_ptr->send_queue);
00895 vip_cq_ptr = vip_vi_ptr->send_queue.vip_cq_ptr;
00896 vip_desc_ptr = vip_vi_ptr->send_queue.current_desc;
00897
00898 while (vip_desc_ptr != NULL)
00899 {
00900
00901 if (vip_check_memory_handle (vip_nic_ptr,
00902 vip_vi_queue_ptr->current_mem,
00903 (VIP_UINTPTR) vip_desc_ptr,
00904 sizeof (VIP_CONTROL_SEGMENT),
00905 vip_vi_ptr->vip_ptag_ptr->id)
00906 != VIP_SUCCESS)
00907 {
00908 VIP_DEBUG (("Control segment Memory Handle completion check error"));
00909 goto next_send_desc;
00910 }
00911
00912 if ((vip_desc_ptr->CS.Status & VIP_STATUS_DONE) == 0)
00913 {
00914 vip_desc_ptr->CS.Status |= VIP_STATUS_DESC_FLUSHED_ERROR;
00915 vip_desc_ptr->CS.Status |= VIP_STATUS_DONE;
00916
00917
00918 if (vip_vi_queue_ptr->event_count > 0)
00919 {
00920 VIP_EVENT_SIGNAL (&(vip_vi_queue_ptr->event));
00921 }
00922 }
00923
00924 if (vip_cq_ptr != NULL)
00925 {
00926
00927 VIP_DEBUG (("Notify completion queue"));
00928 vip_cq_entry_ptr =
00929 &(vip_cq_ptr->queue[vip_cq_ptr->next_completion]);
00930 vip_cq_entry_ptr->vip_vi_ptr = vip_vi_ptr;
00931 vip_cq_entry_ptr->recv_queue = VIP_FALSE;
00932 vip_cq_entry_ptr->completed = VIP_TRUE;
00933
00934
00935 if ((vip_cq_ptr->next_completion + 1) < vip_cq_ptr->count)
00936 {
00937 vip_cq_ptr->next_completion++;
00938 }
00939 else
00940 {
00941 vip_cq_ptr->next_completion = 0;
00942 }
00943
00944 if (vip_cq_ptr->event_count > 0)
00945 {
00946 VIP_EVENT_SIGNAL (&(vip_cq_ptr->event));
00947 }
00948 }
00949
00950 next_send_desc:
00951 VIP_ASSERT ((vip_vi_queue_ptr->last != vip_desc_ptr)
00952 || (vip_desc_ptr->CS.Next.Address == NULL));
00953 vip_vi_queue_ptr->current_desc = vip_desc_ptr->CS.Next.Address;
00954 vip_vi_queue_ptr->current_mem = vip_desc_ptr->CS.NextHandle;
00955 vip_desc_ptr = vip_vi_queue_ptr->current_desc;
00956 }
00957 VIP_ASSERT (vip_vi_queue_ptr->current_desc == NULL);
00958 vip_vi_queue_ptr->current_mem = 0;
00959 vip_vi_queue_ptr->count_to_process = 0;
00960
00961
00962 if (send_conn_lost == VIP_TRUE)
00963 {
00964
00965
00966 vip_millisleep (100);
00967 vip_return_report (vip_nic_ptr->vip_gm_ptr, vip_nic_ptr, vip_vi_ptr,
00968 VIP_REPORT_CONN_LOST, VIP_TRUE);
00969 }
00970 VIP_DEBUG (("Success"));
00971 }
00972
00996 VIP_RETURN
00997 vip_check_memory_handle (VIP_NIC * vip_nic_ptr,
00998 VIP_MEM_HANDLE vip_mem_handle,
00999 VIP_UINT64 range_start,
01000 VIP_UINT64 range_length,
01001 VIP_UINT32 vip_vi_ptag_id)
01002 {
01003 VIP_MEM *vip_mem_ptr;
01004 VIP_DEBUG_LABEL (("vip_check_memory_handle"));
01005
01006 VIP_ASSERT_MUTEX_LOCKED (&(vip_nic_ptr->lock));
01007
01008
01009 if ((vip_mem_handle == 0) || (vip_mem_handle > VI_GM_MAX_REGISTER_REGIONS))
01010 {
01011 VIP_DEBUG (("Memory Handle is out of range"));
01012 return VIP_INVALID_PARAMETER;
01013 }
01014
01015
01016 vip_mem_ptr = vip_nic_ptr->vip_mem_handle_ptrs[vip_mem_handle];
01017 if (VIP_INVALID_MEM_HANDLE (vip_mem_ptr))
01018 {
01019 VIP_DEBUG (("Invalid Memory Handle"));
01020 return VIP_INVALID_PARAMETER;
01021 }
01022
01023
01024 if (vip_mem_ptr->handle.vip_nic_ptr != vip_nic_ptr)
01025 {
01026 VIP_DEBUG (("Memory Handle from another NIC"));
01027 return VIP_INVALID_PARAMETER;
01028 }
01029
01030 if (range_start + range_length < range_start)
01031 {
01032 VIP_DEBUG (("Segment overflow"));
01033 return VIP_INVALID_PARAMETER;
01034 }
01035
01036
01037 if (((VIP_UINT64) ((VIP_UINTPTR) vip_mem_ptr->address) > range_start)
01038 || ((((VIP_UINT64) ((VIP_UINTPTR) vip_mem_ptr->address))
01039 + vip_mem_ptr->length) < (range_start + range_length)))
01040 {
01041 VIP_DEBUG (("Segment not covered by Memory Handle"));
01042 return VIP_INVALID_PARAMETER;
01043 }
01044
01045
01046 if (VIP_INVALID_PTAG_HANDLE (vip_mem_ptr->vip_ptag_ptr))
01047 {
01048 VIP_DEBUG (("Invalid MEM PTAG handle"));
01049 return VIP_INVALID_PARAMETER;
01050 }
01051
01052
01053 if (vip_mem_ptr->vip_ptag_ptr->handle.vip_nic_ptr != vip_nic_ptr)
01054 {
01055 VIP_DEBUG (("Ptag Handle from another NIC"));
01056 return VIP_INVALID_PARAMETER;
01057 }
01058
01059
01060 if (vip_mem_ptr->vip_ptag_ptr->id != vip_vi_ptag_id)
01061 {
01062 VIP_DEBUG (("VI PTAG and MEM PTAG do not match"));
01063 return VIP_INVALID_PARAMETER;
01064 }
01065
01066 VIP_DEBUG (("Success"));
01067 return VIP_SUCCESS;
01068 }
01069
01083 void
01084 vip_alive_alarm_callback (void *ptr)
01085 {
01086 VIP_GM *vip_gm_ptr;
01087 VIP_PACKET_ALIVE *pkt_ptr;
01088 VIP_DEBUG_LABEL (("vip_alive_alarm_callback"));
01089
01090 vip_gm_ptr = (VIP_GM *) ptr;
01091 VIP_ASSERT (vip_gm_ptr->alive_buffer != NULL);
01092 VIP_ASSERT_MUTEX_LOCKED (&(vip_gm_ptr->lock));
01093 pkt_ptr = vip_gm_ptr->alive_buffer;
01094
01095 if (VIP_NTOH_UINT32 (pkt_ptr->net_srv_magic) == 0)
01096 {
01097
01098 pkt_ptr->type = VIP_HTON_UCHAR (VIP_ALIVE_PKT);
01099 pkt_ptr->net_srv_magic = VIP_HTON_UINT32 (vip_gm_ptr->magic);
01100 gm_send_with_callback (vip_gm_ptr->gm_port, pkt_ptr,
01101 VI_GM_CTRL_GM_SIZE,
01102 sizeof (VIP_PACKET_ALIVE),
01103 GM_LOW_PRIORITY,
01104 vip_gm_ptr->conn_mgr_gm_id,
01105 VI_GM_PORT_CONN_MANAGER,
01106 vip_alive_sent_callback, vip_gm_ptr);
01107
01108 gm_set_alarm (vip_gm_ptr->gm_port, &(vip_gm_ptr->alive_alarm),
01109 ((VI_GM_CONN_MGR_TTL * 1000) / 4),
01110 vip_alive_alarm_callback, vip_gm_ptr);
01111 }
01112 else
01113 {
01114 VIP_DEBUG (("Previous heartbeat message sent completion too late"));
01115 gm_set_alarm (vip_gm_ptr->gm_port, &(vip_gm_ptr->alive_alarm),
01116 ((VI_GM_CONN_MGR_TTL * 1000) / 2),
01117 vip_alive_alarm_callback, vip_gm_ptr);
01118 }
01119
01120 VIP_DEBUG (("Heartbeat message sent to connection manager"));
01121 }
01122
01138 void
01139 vip_alive_sent_callback (struct gm_port *gm_port,
01140 void *context,
01141 gm_status_t status)
01142 {
01143 VIP_GM *vip_gm_ptr;
01144 VIP_DEBUG_LABEL (("vip_alive_sent_callback"));
01145
01146 vip_gm_ptr = (VIP_GM *) context;
01147 VIP_ASSERT_MUTEX_LOCKED (&(vip_gm_ptr->lock));
01148 if (status != GM_SUCCESS)
01149 {
01150 VIP_NOTICE (("Heartbeat message to Connection Manager "
01151 "(GM id %d, port %d) completed with error (%s)\n",
01152 vip_gm_ptr->conn_mgr_gm_id, VI_GM_PORT_CONN_MANAGER,
01153 gm_strerror (status)));
01154 gm_resume_sending (gm_port, GM_LOW_PRIORITY,
01155 vip_gm_ptr->conn_mgr_gm_id,
01156 VI_GM_PORT_CONN_MANAGER,
01157 vip_alive_sent_callback, context);
01158 return;
01159 }
01160
01161
01162 vip_gm_ptr->alive_buffer->net_srv_magic = VIP_HTON_UINT32 (0);
01163 VIP_DEBUG (("Success"));
01164 }
01165
01166
01179 void
01180 vip_remove_conn_waiting_list (VIP_GM * vip_gm_ptr, VIP_CONN * vip_conn_ptr)
01181 {
01182 VIP_DEBUG_LABEL (("vip_remove_conn_waiting_list"));
01183
01184 VIP_ASSERT_MUTEX_LOCKED (&(vip_gm_ptr->lock));
01185 VIP_ASSERT_MUTEX_LOCKED (&(vip_conn_ptr->handle.vip_nic_ptr->lock));
01186 VIP_ASSERT (vip_conn_ptr->waiting_list == VIP_TRUE);
01187
01188
01189 if (vip_conn_ptr->prev_waiting_conn_ptr == NULL)
01190 {
01191 VIP_ASSERT (vip_conn_ptr == vip_gm_ptr->head_waiting_conn_ptr);
01192 vip_gm_ptr->head_waiting_conn_ptr = vip_conn_ptr->next_waiting_conn_ptr;
01193 }
01194 else
01195 {
01196 vip_conn_ptr->prev_waiting_conn_ptr->next_waiting_conn_ptr =
01197 vip_conn_ptr->next_waiting_conn_ptr;
01198 }
01199
01200
01201 if (vip_conn_ptr->next_waiting_conn_ptr == NULL)
01202 {
01203 VIP_ASSERT (vip_conn_ptr == vip_gm_ptr->tail_waiting_conn_ptr);
01204 vip_gm_ptr->tail_waiting_conn_ptr = vip_conn_ptr->prev_waiting_conn_ptr;
01205 }
01206 else
01207 {
01208 vip_conn_ptr->next_waiting_conn_ptr->prev_waiting_conn_ptr =
01209 vip_conn_ptr->prev_waiting_conn_ptr;
01210 }
01211
01212 vip_conn_ptr->waiting_list = VIP_FALSE;
01213 VIP_DEBUG (("Success"));
01214 }
01215
01229 void
01230 vip_conn_peer_request_alarm_callback (void *ptr)
01231 {
01232 VIP_GM *vip_gm_ptr;
01233 VIP_CONN *vip_conn_ptr;
01234 VIP_DEBUG_LABEL (("vip_conn_peer_request_alarm_callback"));
01235
01236
01237 vip_conn_ptr = (VIP_CONN *) ptr;
01238 if (VIP_INVALID_CONN_HANDLE (vip_conn_ptr))
01239 {
01240 VIP_DEBUG (("Invalid CONN handle ptr in conn peer request alarm"));
01241 return;
01242 }
01243 VIP_MUTEX_LOCK (&(vip_conn_ptr->handle.vip_nic_ptr->lock));
01244
01245
01246 if (vip_conn_ptr->status == VIP_NOT_DONE)
01247 {
01248 vip_gm_ptr = vip_conn_ptr->handle.vip_nic_ptr->vip_gm_ptr;
01249 vip_remove_conn_waiting_list (vip_gm_ptr, vip_conn_ptr);
01250 vip_conn_ptr->status = VIP_TIMEOUT;
01251 VIP_EVENT_SIGNAL (&(vip_conn_ptr->event));
01252 }
01253
01254 VIP_MUTEX_UNLOCK (&(vip_conn_ptr->handle.vip_nic_ptr->lock));
01255 VIP_DEBUG (("Success"));
01256 }
01257
01275 int
01276 vip_avl_compare_function (const void *a, const void *b, void *param)
01277 {
01278 if (((VIP_AVL_RANGE *) (a))->addr < ((VIP_AVL_RANGE *) (b))->addr)
01279 {
01280 return -1;
01281 }
01282 else
01283 {
01284 if (((VIP_AVL_RANGE *) (a))->addr
01285 >= (((VIP_AVL_RANGE *) (b))->addr + ((VIP_AVL_RANGE *) (b))->length))
01286 {
01287 return 1;
01288 }
01289 else
01290 {
01291 return 0;
01292 }
01293 }
01294 }
01295
01308 void
01309 vip_avl_free_function (void * data, void * param)
01310 {
01311 gm_lookaside_free (data);
01312 }
01313
01334 VIP_UINT32
01335 vip_avl_register_memory (VIP_GM * vip_gm_ptr,
01336 VIP_UINTPTR start,
01337 VIP_UINTPTR end)
01338 {
01339 VIP_UINTPTR addr;
01340 VIP_UINTPTR batch_addr;
01341 VIP_UINT32 batch_pages;
01342 VIP_AVL_RANGE *vip_avl_range_ptr;
01343 VIP_AVL_RANGE *vip_old_avl_range_ptr;
01344 gm_status_t gm_status;
01345 VIP_DEBUG_LABEL (("vip_avl_register_memory"));
01346
01347 VIP_ASSERT (start < end);
01348 VIP_ASSERT ((start % GM_PAGE_LEN) == 0);
01349 VIP_ASSERT ((end % GM_PAGE_LEN) == 0);
01350 VIP_ASSERT_MUTEX_LOCKED (&(vip_gm_ptr->lock));
01351
01352
01353 vip_avl_range_ptr =
01354 (VIP_AVL_RANGE *) gm_lookaside_alloc (vip_gm_ptr->regmem_avl_lookaside);
01355 if (vip_avl_range_ptr == NULL)
01356 {
01357 VIP_DEBUG (("Unable to allocate AVL range from lookaside list"));
01358 return 0;
01359 }
01360
01361 addr = start;
01362 batch_addr = 0;
01363 batch_pages = 0;
01364
01365
01366 while (addr < end)
01367 {
01368 vip_avl_range_ptr->addr = addr;
01369 vip_avl_range_ptr->length = GM_PAGE_LEN;
01370 vip_avl_range_ptr->count = 1;
01371 vip_old_avl_range_ptr = VIP_AVL_TREE_FIND (vip_gm_ptr->regmem_avl_tree,
01372 vip_avl_range_ptr);
01373
01374 if (vip_old_avl_range_ptr == NULL)
01375 {
01376
01377 if (batch_addr == 0)
01378 {
01379 batch_addr = addr;
01380 }
01381 batch_pages++;
01382 }
01383 else
01384 {
01385
01386 VIP_ASSERT ((vip_old_avl_range_ptr->addr <= addr)
01387 && (vip_old_avl_range_ptr->addr
01388 + vip_old_avl_range_ptr->length > addr)) ;
01389
01390 if (batch_addr != 0)
01391 {
01392 VIP_ASSERT (vip_old_avl_range_ptr->addr == addr);
01393
01394
01395 VIP_ENTER_IOCTL (vip_gm_ptr);
01396 gm_status = gm_register_memory (vip_gm_ptr->gm_port,
01397 ((VIP_PVOID) batch_addr),
01398 batch_pages * GM_PAGE_LEN);
01399 VIP_EXIT_IOCTL (vip_gm_ptr);
01400
01401 if (gm_status != GM_SUCCESS)
01402 {
01403 VIP_DEBUG_GM (("gm_register_memory() failed"));
01404 gm_lookaside_free (vip_avl_range_ptr);
01405 return (batch_addr - start);
01406 }
01407
01408 vip_avl_range_ptr->addr = batch_addr;
01409 vip_avl_range_ptr->length = batch_pages * GM_PAGE_LEN;
01410 vip_avl_range_ptr->count = 1;
01411 VIP_AVL_TREE_INSERT (vip_gm_ptr->regmem_avl_tree,
01412 vip_avl_range_ptr);
01413
01414
01415 vip_avl_range_ptr = (VIP_AVL_RANGE *)
01416 gm_lookaside_alloc (vip_gm_ptr->regmem_avl_lookaside);
01417 if (vip_avl_range_ptr == NULL)
01418 {
01419 VIP_DEBUG (("Unable to allocate AVL range from lookaside"));
01420 return (batch_addr - start + (batch_pages * GM_PAGE_LEN));
01421 }
01422
01423 batch_addr = 0;
01424 batch_pages = 0;
01425 }
01426
01427
01428 if (vip_old_avl_range_ptr->addr < addr)
01429 {
01430
01431
01432 vip_avl_range_ptr->addr = vip_old_avl_range_ptr->addr;
01433 vip_avl_range_ptr->length = addr - vip_old_avl_range_ptr->addr;
01434 VIP_ASSERT ((vip_avl_range_ptr->length % GM_PAGE_LEN) == 0);
01435 vip_avl_range_ptr->count = vip_old_avl_range_ptr->count;
01436
01437
01438 vip_old_avl_range_ptr->addr = addr;
01439 vip_old_avl_range_ptr->length -= vip_avl_range_ptr->length;
01440
01441 VIP_AVL_TREE_INSERT (vip_gm_ptr->regmem_avl_tree,
01442 vip_avl_range_ptr);
01443
01444
01445 vip_avl_range_ptr = (VIP_AVL_RANGE *)
01446 gm_lookaside_alloc (vip_gm_ptr->regmem_avl_lookaside);
01447 if (vip_avl_range_ptr == NULL)
01448 {
01449 VIP_DEBUG (("Unable to allocate AVL range from lookaside"));
01450 return (addr - start);
01451 }
01452 }
01453
01454
01455
01456
01457 if ((vip_old_avl_range_ptr->addr
01458 + vip_old_avl_range_ptr->length) > end)
01459 {
01460
01461
01462 vip_avl_range_ptr->addr = end;
01463 vip_avl_range_ptr->length = (vip_old_avl_range_ptr->addr
01464 + vip_old_avl_range_ptr->length
01465 - end);
01466 vip_avl_range_ptr->count = vip_old_avl_range_ptr->count;
01467
01468
01469 vip_old_avl_range_ptr->length -= vip_avl_range_ptr->length;
01470 vip_old_avl_range_ptr->count++;
01471
01472 VIP_AVL_TREE_INSERT (vip_gm_ptr->regmem_avl_tree,
01473 vip_avl_range_ptr);
01474
01475 VIP_DEBUG (("Success"));
01476 return (end - start);
01477 }
01478 else
01479 {
01480 if ((vip_old_avl_range_ptr->addr
01481 + vip_old_avl_range_ptr->length) == end)
01482 {
01483 vip_old_avl_range_ptr->count++;
01484 gm_lookaside_free (vip_avl_range_ptr);
01485 VIP_DEBUG (("Success"));
01486 return (end - start);
01487 }
01488 else
01489 {
01490 VIP_ASSERT ((vip_old_avl_range_ptr->addr
01491 + vip_old_avl_range_ptr->length) < end);
01492 vip_old_avl_range_ptr->count++;
01493 addr = addr + vip_old_avl_range_ptr->length - GM_PAGE_LEN;
01494 }
01495 }
01496 }
01497
01498 addr += GM_PAGE_LEN;
01499 }
01500
01501 VIP_ASSERT (batch_addr != 0);
01502
01503
01504 VIP_ENTER_IOCTL (vip_gm_ptr);
01505 gm_status = gm_register_memory (vip_gm_ptr->gm_port,
01506 ((VIP_PVOID) batch_addr),
01507 batch_pages * GM_PAGE_LEN);
01508 VIP_EXIT_IOCTL (vip_gm_ptr);
01509
01510 if (gm_status != GM_SUCCESS)
01511 {
01512 VIP_DEBUG_GM (("gm_register_memory() failed"));
01513 gm_lookaside_free (vip_avl_range_ptr);
01514 return (batch_addr - start);
01515 }
01516 else
01517 {
01518 vip_avl_range_ptr->addr = batch_addr;
01519 vip_avl_range_ptr->length = batch_pages * GM_PAGE_LEN;
01520 vip_avl_range_ptr->count = 1;
01521 VIP_AVL_TREE_INSERT (vip_gm_ptr->regmem_avl_tree,
01522 vip_avl_range_ptr);
01523 VIP_DEBUG (("Success"));
01524 return (end - start);
01525 }
01526
01527 VIP_ABORT (("Memory registration internal error"));
01528 return 0;
01529 }
01530
01552 VIP_RETURN
01553 vip_avl_deregister_memory (VIP_GM * vip_gm_ptr,
01554 VIP_UINTPTR start,
01555 VIP_UINTPTR end)
01556 {
01557 VIP_UINTPTR addr;
01558 VIP_AVL_RANGE vip_avl_range;
01559 VIP_AVL_RANGE *vip_old_avl_range_ptr;
01560 gm_status_t gm_status;
01561 VIP_DEBUG_LABEL (("vip_avl_deregister_memory"));
01562
01563 VIP_ASSERT (start < end);
01564 VIP_ASSERT ((start % GM_PAGE_LEN) == 0);
01565 VIP_ASSERT ((end % GM_PAGE_LEN) == 0);
01566 VIP_ASSERT_MUTEX_LOCKED (&(vip_gm_ptr->lock));
01567
01568 addr = start;
01569 while (addr < end)
01570 {
01571 vip_avl_range.addr = addr;
01572 vip_avl_range.length = GM_PAGE_LEN;
01573 vip_avl_range.count = 1;
01574 vip_old_avl_range_ptr = VIP_AVL_TREE_FIND (vip_gm_ptr->regmem_avl_tree,
01575 &(vip_avl_range));
01576 VIP_ASSERT (vip_old_avl_range_ptr != NULL);
01577 VIP_ASSERT (vip_old_avl_range_ptr->addr == addr);
01578 VIP_ASSERT ((vip_old_avl_range_ptr->addr
01579 + vip_old_avl_range_ptr->length) <= end);
01580
01581 if (vip_old_avl_range_ptr->count == 1)
01582 {
01583
01584 VIP_ENTER_IOCTL (vip_gm_ptr);
01585 gm_status =
01586 gm_deregister_memory (vip_gm_ptr->gm_port,
01587 ((VIP_PVOID) vip_old_avl_range_ptr->addr),
01588 vip_old_avl_range_ptr->length);
01589 VIP_EXIT_IOCTL (vip_gm_ptr);
01590
01591 if (gm_status != GM_SUCCESS)
01592 {
01593 VIP_DEBUG_GM (("gm_deregister_memory() failed"));
01594 return VIP_ERROR_RESOURCE;
01595 }
01596
01597
01598 VIP_AVL_TREE_DELETE (vip_gm_ptr->regmem_avl_tree, vip_old_avl_range_ptr);
01599 addr += vip_old_avl_range_ptr->length;
01600 gm_lookaside_free (vip_old_avl_range_ptr);
01601 }
01602 else
01603 {
01604 vip_old_avl_range_ptr->count--;
01605 addr += vip_old_avl_range_ptr->length;
01606 }
01607 }
01608
01609 VIP_DEBUG (("Success"));
01610 return VIP_SUCCESS;
01611 }