Main Page | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

vipl_priv.c

Go to the documentation of this file.
00001 /********************************************************
00002  * Myricom VI-GM  networking software and documentation *
00003  * Copyright (c) 2001 by Myricom, Inc.                  *
00004  * All rights reserved.                                 *
00005  * See the file `COPYING' for copyright notice.         *
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 /* conversion functions */
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 /* debug functions */
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 /* event functions */
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   /* check MemoryHandle */
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       /* VI in error state if fatal report */
00750       if (vip_vi_ptr->state != VIP_STATE_ERROR)
00751         {
00752           /* the VI transition to error state */
00753           vip_vi_transition_to_error_state (vip_vi_ptr, VIP_TRUE);
00754 
00755           /* a connection lost asynchronous error is generated */
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       /* signal the completion to a thread blocking on the queue */
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       /* generate an entry in the completion queue */
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       /* shift the completion queue entry to the next available */
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       /* wake up any VipCQWait() */
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   /* recv queue */
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           /* signal the completion to a thread blocking on the queue */
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           /* generate an entry in the completion queue */
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           /* shift the completion queue entry to the next available */
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   /* send queue */
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       /* check MemoryHandle */
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           /* signal the completion to a thread blocking on the queue */
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           /* generate an entry in the completion queue */
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           /* shift the completion queue entry to the next available */
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   /* send a connection lost report to the other end */
00962   if (send_conn_lost == VIP_TRUE)
00963     {
00964       /* a little delay to be sure that the send callbacks 
00965          have been processed before receiving this report. */
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   /* check the MemoryHandle */
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   /* check regmem handle */
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   /* check regmem's NIC */
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   /* check memory handle coverage */
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   /* check MEM PTAG handle */
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   /* check ptag's NIC */
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   /* compare PTAG ids */
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       /* the previous heartbeat has been sent */
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   /* notify the send completion for next alive alarm */
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   /* if the connection is the head of the waiting list */
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   /* if the connection is the tail of the waiting list */
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   /* check the connection */
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   /* complete the connection if needed */
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   /* allocate an AVL tree entry */
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   /* look into the AVL tree if pages are already registered */
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           /* page not allocated, one more to register */
01377           if (batch_addr == 0)
01378             {
01379               batch_addr = addr;
01380             }
01381           batch_pages++;
01382         }
01383       else
01384         {
01385           /* page already allocated */
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               /* try to register previously unregistered pages */
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               /* allocate another AVL tree entry */
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           /* Check if the old segment start before the new one */
01428           if (vip_old_avl_range_ptr->addr < addr)
01429             {
01430               /* build a new range for the part of the old segment 
01431                  before the new one */
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               /* change the beginning of the rest to align on the new range */
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               /* allocate another AVL tree entry */
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           /* now the old segment and the new one are aligned, 
01456              let's look at the end */
01457           if ((vip_old_avl_range_ptr->addr
01458                + vip_old_avl_range_ptr->length) > end)
01459             {
01460               /* build a new range for the part of the old segment 
01461                  after the new one */
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               /* shrink the old segment and increase the reference count */
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   /* try to register previously unregistered pages */
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           /* deregister memory */
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           /* remove the entry in the AVL tree */
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 }
VI-GM-1.3 by Myricom © 1997-2006. Documentation generated on 20 May 2006 by doxygen 1.4.4.