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

vipl_priv_send.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 
00014 #include <stdlib.h>
00015 #include <string.h>
00016 
00017 #include "vipl_priv.h"
00018 
00031 void
00032 vip_process_send_desc (VIP_VI * vip_vi_ptr)
00033 {
00034   VIP_NIC *vip_nic_ptr;
00035   VIP_GM *vip_gm_ptr;
00036   VIP_UINT32 vip_vi_ptag_id;
00037   VIP_UINT32 total_length;
00038   VIP_UINT32 i;
00039   VIP_UINT32 address_segment;
00040   VIP_PACKET *pkt_ptr;
00041   VIP_PVOID data_ptr;
00042 #ifdef VI_GM_FAST_RDMA
00043   VIP_PVOID64 target_ptr;
00044 #endif
00045   VIP_DESCRIPTOR *vip_desc_ptr;
00046   VIP_SEND_REQ *vip_send_req_ptr;
00047   VIP_DATA_SEGMENT *vip_data_segment_ptr;
00048   VIP_DEBUG_LABEL (("vip_process_send_desc"));
00049 
00050   vip_nic_ptr = vip_vi_ptr->handle.vip_nic_ptr;
00051   vip_gm_ptr = vip_nic_ptr->vip_gm_ptr;
00052   VIP_ASSERT_MUTEX_LOCKED (&(vip_gm_ptr->lock));
00053   VIP_ASSERT_MUTEX_LOCKED (&(vip_nic_ptr->lock));
00054 
00055   vip_desc_ptr = vip_vi_ptr->send_queue.current_desc;
00056   vip_vi_ptag_id = vip_vi_ptr->vip_ptag_ptr->id;
00057 
00058   /* check that the descriptor is aligned on a 64 Bytes boundary */
00059   if ((((VIP_UINTPTR) vip_desc_ptr) & 0x3F) != 0)
00060     {
00061       VIP_DEBUG (("Descriptor is not aligned on a 64 Bytes boundary"));
00062       goto async_post_desc_error;
00063     }
00064 
00065   /* check MemoryHandle */
00066   if (vip_check_memory_handle (vip_nic_ptr,
00067                                vip_vi_ptr->send_queue.current_mem,
00068                                (VIP_UINTPTR) vip_desc_ptr,
00069                                sizeof (VIP_CONTROL_SEGMENT),
00070                                vip_vi_ptag_id) != VIP_SUCCESS)
00071     {
00072       VIP_DEBUG (("Control segment Memory Handle check error"));
00073       goto async_post_desc_error;
00074     }
00075 
00076   /* check reserved part of the control field */
00077   if ((vip_desc_ptr->CS.Control & VIP_CONTROL_RESERVED) != 0)
00078     {
00079       VIP_DEBUG (("Control field reserved part is not set to 0"));
00080       vip_desc_ptr->CS.Status |= VIP_STATUS_FORMAT_ERROR;
00081       goto out_with_sync_error;
00082     }
00083 
00084   /* check that the Reserved field is set to 0 */
00085   if (vip_desc_ptr->CS.Reserved != 0)
00086     {
00087       VIP_DEBUG (("Reserved field is not set to 0"));
00088       vip_desc_ptr->CS.Status |= VIP_STATUS_FORMAT_ERROR;
00089       goto out_with_sync_error;
00090     }
00091 
00092   /* check number of segments */
00093   if (vip_desc_ptr->CS.SegCount > VI_GM_MAX_SEGMENTS_PER_DESCRIPTOR)
00094     {
00095       VIP_DEBUG (("Number of Address/Data segments is exceeding capacity "
00096                   "(max=%d)", VI_GM_MAX_SEGMENTS_PER_DESCRIPTOR));
00097       vip_desc_ptr->CS.Status |= VIP_STATUS_LENGTH_ERROR;
00098       goto out_with_sync_error;
00099     }
00100 
00101   /* check length of data */
00102   VIP_ASSERT (vip_vi_ptr->mtu <= VI_GM_MAX_TRANSFER_SIZE);
00103   if (vip_desc_ptr->CS.Length > vip_vi_ptr->mtu)
00104     {
00105       VIP_DEBUG (("Data length is exceeding the MTU of the VI"));
00106       vip_desc_ptr->CS.Status |= VIP_STATUS_LENGTH_ERROR;
00107       goto out_with_sync_error;
00108     }
00109 
00110   /* check MemoryHandle for data */
00111   if (vip_check_memory_handle (vip_nic_ptr,
00112                                vip_vi_ptr->send_queue.current_mem,
00113                                (VIP_UINTPTR) vip_desc_ptr,
00114                                (sizeof (VIP_CONTROL_SEGMENT)
00115                                 + (vip_desc_ptr->CS.SegCount
00116                                    * sizeof (VIP_DESCRIPTOR_SEGMENT))),
00117                                vip_vi_ptag_id) != VIP_SUCCESS)
00118     {
00119       VIP_DEBUG (("Data segments not covered by Memory Handle"));
00120       vip_desc_ptr->CS.Status |= VIP_STATUS_PROTECTION_ERROR;
00121       goto out_with_sync_error;
00122     }
00123 
00124   /* check VI state */
00125   if (vip_vi_ptr->state != VIP_STATE_CONNECTED)
00126     {
00127       VIP_DEBUG (("VI is not connected"));
00128       vip_desc_ptr->CS.Status |= VIP_STATUS_DESC_FLUSHED_ERROR;
00129       goto out_with_sync_error;
00130     }
00131 
00132   /* check the operation type */
00133   switch (vip_desc_ptr->CS.Control & VIP_CONTROL_OP_MASK)
00134     {
00135     case VIP_CONTROL_OP_SENDRECV:
00136       address_segment = 0;
00137       break;
00138 
00139     case VIP_CONTROL_OP_RDMAWRITE:
00140       address_segment = 1;
00141       break;
00142 
00143     case VIP_CONTROL_OP_RDMAREAD:
00144       VIP_DEBUG (("RDMA Read operation not supported"));
00145       vip_desc_ptr->CS.Status |= VIP_STATUS_FORMAT_ERROR;
00146       goto out_with_sync_error;
00147 
00148     default:
00149       VIP_DEBUG (("Control field Operation type is set to Reserved value"));
00150       vip_desc_ptr->CS.Status |= VIP_STATUS_FORMAT_ERROR;
00151       goto out_with_sync_error;
00152     }
00153 
00154   /* check the Data segments */
00155   total_length = 0;
00156   for (i = address_segment; i < vip_desc_ptr->CS.SegCount; i++)
00157     {
00158       vip_data_segment_ptr = &(vip_desc_ptr->DS[i].Local);
00159 
00160       /* check data segment length */
00161       if (vip_data_segment_ptr->Length > VI_GM_MAX_TRANSFER_SIZE)
00162         {
00163           VIP_DEBUG (("Length of a data segment is exceeding the maximum "
00164                       "transfert size (max=%d)", VI_GM_MAX_TRANSFER_SIZE));
00165           vip_desc_ptr->CS.Status |= VIP_STATUS_LENGTH_ERROR;
00166           goto out_with_sync_error;
00167         }
00168 
00169       /* check the data segment memory protection */
00170       if (vip_check_memory_handle (vip_nic_ptr,
00171                                    vip_data_segment_ptr->Handle,
00172                                    (VIP_UINTPTR) 
00173                                    vip_data_segment_ptr->Data.Address,
00174                                    vip_data_segment_ptr->Length,
00175                                    vip_vi_ptag_id) != VIP_SUCCESS)
00176         {
00177           VIP_DEBUG (("Data segment Memory Handle check error"));
00178           vip_desc_ptr->CS.Status |= VIP_STATUS_PROTECTION_ERROR;
00179           goto out_with_sync_error;
00180         }
00181 
00182       total_length += vip_data_segment_ptr->Length;
00183     }
00184 
00185   /* check the total length consistency */
00186   if (total_length != vip_desc_ptr->CS.Length)
00187     {
00188       VIP_DEBUG (("Data total length is different than Length field"));
00189       vip_desc_ptr->CS.Status |= VIP_STATUS_LENGTH_ERROR;
00190       goto out_with_sync_error;
00191     }
00192 
00193   /* Processing regular send or RDMA Write ? */
00194   if ((vip_desc_ptr->CS.Control
00195        & VIP_CONTROL_OP_MASK) == VIP_CONTROL_OP_SENDRECV)
00196     {
00197       vip_desc_ptr->CS.Status |= VIP_STATUS_OP_SEND;
00198 
00199       /* Eager or Rendez-vous (use the biggest packet format here) */
00200       if ((total_length + sizeof (VIP_PACKET_EAGER_IMM_RR))
00201           <= VI_GM_EAGER_LENGTH)
00202         {
00203           /* immediate data ? */
00204           if ((vip_desc_ptr->CS.Control & VIP_CONTROL_IMMEDIATE) != 0)
00205             {
00206               VIP_DEBUG (("Eager with immediate (desc=%p)", vip_desc_ptr));
00207               switch (vip_vi_ptr->reliability)
00208                 {
00209                 case VIP_SERVICE_UNRELIABLE:
00210                   vip_send_req_ptr =
00211                     vip_allocate_packet (vip_gm_ptr, total_length
00212                                          + sizeof (VIP_PACKET_EAGER_IMM_UR));
00213                   VIP_ASSERT (vip_send_req_ptr != NULL);
00214                   pkt_ptr = (VIP_PACKET *) (vip_send_req_ptr->ptr);
00215                   data_ptr = &(pkt_ptr->vip_pkt_eager_imm_ur.net_imm_data);
00216                   if ((total_length + sizeof (VIP_PACKET_EAGER_IMM_UR))
00217                       <= gm_mtu (vip_gm_ptr->gm_port))
00218                     {
00219                       vip_send_req_ptr->type |= VIP_SEND_REQ_UNRELIABLE;
00220                     }
00221                   VIP_FILL_GENERIC_HEAD (pkt_ptr, total_length, vip_vi_ptr,
00222                                          VIP_EAGER_IMM_PKT);
00223                   break;
00224 
00225                 case VIP_SERVICE_RELIABLE_DELIVERY:
00226                   vip_send_req_ptr =
00227                     vip_allocate_packet (vip_gm_ptr, total_length
00228                                          + sizeof (VIP_PACKET_EAGER_IMM_RD));
00229                   VIP_ASSERT (vip_send_req_ptr != NULL);
00230                   pkt_ptr = (VIP_PACKET *) (vip_send_req_ptr->ptr);
00231                   data_ptr = &(pkt_ptr->vip_pkt_eager_imm_rd.net_imm_data);
00232                   VIP_FILL_GENERIC_HEAD (pkt_ptr, total_length, vip_vi_ptr,
00233                                          VIP_EAGER_IMM_PKT);
00234                   pkt_ptr->vip_pkt_eager_imm_rd.net_local_nic_index =
00235                     VIP_HTON_UINT16 (vip_nic_ptr->index);
00236                   pkt_ptr->vip_pkt_eager_imm_rd.net_local_vi_index =
00237                     VIP_HTON_UINT16 (vip_vi_ptr->index);
00238                   break;
00239 
00240                 case VIP_SERVICE_RELIABLE_RECEPTION:
00241                   vip_send_req_ptr =
00242                     vip_allocate_packet (vip_gm_ptr, total_length
00243                                          + sizeof (VIP_PACKET_EAGER_IMM_RR));
00244                   VIP_ASSERT (vip_send_req_ptr != NULL);
00245                   pkt_ptr = (VIP_PACKET *) (vip_send_req_ptr->ptr);
00246                   data_ptr = &(pkt_ptr->vip_pkt_eager_imm_rr.net_imm_data);
00247                   VIP_FILL_GENERIC_HEAD (pkt_ptr, total_length, vip_vi_ptr,
00248                                          VIP_EAGER_IMM_PKT);
00249                   pkt_ptr->vip_pkt_eager_imm_rr.net_local_nic_index =
00250                     VIP_HTON_UINT16 (vip_nic_ptr->index);
00251                   pkt_ptr->vip_pkt_eager_imm_rr.net_local_vi_index =
00252                     VIP_HTON_UINT16 (vip_vi_ptr->index);
00253                   break;
00254 
00255                 default:
00256                   VIP_ABORT (("Invalid Reliability level in VI"));
00257                 }
00258 
00259               *(VIP_NET_UINT32*)data_ptr = VIP_HTON_UINT32(vip_desc_ptr->CS.ImmediateData);
00260               data_ptr = (VIP_PVOID) (((VIP_UINTPTR) data_ptr)
00261                                       + sizeof (VIP_UINT32)*2);
00262             }
00263           else
00264             {
00265               VIP_DEBUG (("Eager (desc=%p)", vip_desc_ptr));
00266 
00267               switch (vip_vi_ptr->reliability)
00268                 {
00269                 case VIP_SERVICE_UNRELIABLE:
00270                   vip_send_req_ptr =
00271                     vip_allocate_packet (vip_gm_ptr, total_length
00272                                          + sizeof (VIP_PACKET_EAGER_UR));
00273                   VIP_ASSERT (vip_send_req_ptr != NULL);
00274                   pkt_ptr = (VIP_PACKET *) (vip_send_req_ptr->ptr);
00275                   data_ptr = (VIP_PVOID) (((VIP_UINTPTR) pkt_ptr)
00276                                           + sizeof (VIP_PACKET_EAGER_UR));
00277                   if ((total_length + sizeof (VIP_PACKET_EAGER_UR))
00278                       <= gm_mtu (vip_gm_ptr->gm_port))
00279                     {
00280                       vip_send_req_ptr->type |= VIP_SEND_REQ_UNRELIABLE;
00281                     }
00282 
00283                   VIP_FILL_GENERIC_HEAD (pkt_ptr, total_length, vip_vi_ptr,
00284                                          VIP_EAGER_PKT);
00285                   break;
00286 
00287                 case VIP_SERVICE_RELIABLE_DELIVERY:
00288                   vip_send_req_ptr =
00289                     vip_allocate_packet (vip_gm_ptr, total_length
00290                                          + sizeof (VIP_PACKET_EAGER_RD));
00291                   VIP_ASSERT (vip_send_req_ptr != NULL);
00292                   pkt_ptr = (VIP_PACKET *) (vip_send_req_ptr->ptr);
00293                   data_ptr = (VIP_PVOID) (((VIP_UINTPTR) pkt_ptr)
00294                                           + sizeof (VIP_PACKET_EAGER_RD));
00295                   VIP_FILL_GENERIC_HEAD (pkt_ptr, total_length, vip_vi_ptr,
00296                                          VIP_EAGER_PKT);
00297                   pkt_ptr->vip_pkt_eager_rd.net_local_nic_index =
00298                     VIP_HTON_UINT16 (vip_nic_ptr->index);
00299                   pkt_ptr->vip_pkt_eager_rd.net_local_vi_index =
00300                     VIP_HTON_UINT16 (vip_vi_ptr->index);
00301                   break;
00302 
00303                 case VIP_SERVICE_RELIABLE_RECEPTION:
00304                   vip_send_req_ptr =
00305                     vip_allocate_packet (vip_gm_ptr, total_length
00306                                          + sizeof (VIP_PACKET_EAGER_RR));
00307                   VIP_ASSERT (vip_send_req_ptr != NULL);
00308                   pkt_ptr = (VIP_PACKET *) (vip_send_req_ptr->ptr);
00309                   data_ptr = (VIP_PVOID) (((VIP_UINTPTR) pkt_ptr)
00310                                           + sizeof (VIP_PACKET_EAGER_RR));
00311                   VIP_FILL_GENERIC_HEAD (pkt_ptr, total_length, vip_vi_ptr,
00312                                          VIP_EAGER_PKT);
00313                   pkt_ptr->vip_pkt_eager_rr.net_local_nic_index =
00314                     VIP_HTON_UINT16 (vip_nic_ptr->index);
00315                   pkt_ptr->vip_pkt_eager_rr.net_local_vi_index =
00316                     VIP_HTON_UINT16 (vip_vi_ptr->index);
00317                   break;
00318 
00319                 default:
00320                   VIP_ABORT (("Invalid Reliability level in VI"));
00321                 }
00322             }
00323 
00324           for (i = address_segment; i < vip_desc_ptr->CS.SegCount; i++)
00325             {
00326               memcpy (data_ptr, vip_desc_ptr->DS[i].Local.Data.Address,
00327                       vip_desc_ptr->DS[i].Local.Length);
00328               data_ptr = (VIP_PVOID) (((VIP_UINTPTR) data_ptr)
00329                                       + vip_desc_ptr->DS[i].Local.Length);
00330             }
00331 
00332           if ((vip_send_req_ptr->type & VIP_SEND_REQ_UNRELIABLE) == 0)
00333             {
00334               VIP_ASSERT ((vip_send_req_ptr->type
00335                            & VIP_SEND_REQ_RELIABLE) == 0);
00336               vip_send_req_ptr->type |= VIP_SEND_REQ_RELIABLE;
00337             }
00338 
00339           vip_send_req_ptr->dest_port_id = vip_vi_ptr->gm_dest_port;
00340           vip_send_req_ptr->dest_gm_id = vip_vi_ptr->gm_dest_id;
00341           vip_send_req_ptr->vip_nic_ptr = vip_nic_ptr;
00342           vip_send_req_ptr->vip_vi_ptr = vip_vi_ptr;
00343           vip_send_req_ptr->vip_desc_ptr = vip_desc_ptr;
00344           vip_send_data (vip_send_req_ptr);
00345         }
00346       else
00347         {
00348           /* Rendez-vous */
00349           VIP_DEBUG (("3Way request (desc=%p)", vip_desc_ptr));
00350           vip_send_req_ptr =
00351             vip_allocate_packet (vip_gm_ptr, sizeof (VIP_PACKET_3WAY_REQ));
00352           VIP_ASSERT (vip_send_req_ptr != NULL);
00353           pkt_ptr = (VIP_PACKET *) (vip_send_req_ptr->ptr);
00354           VIP_FILL_GENERIC_HEAD (pkt_ptr, total_length, vip_vi_ptr,
00355                                  VIP_3WAY_REQ_PKT);
00356           pkt_ptr->vip_pkt_3way_req.net_local_nic_index =
00357             VIP_HTON_UINT16 (vip_nic_ptr->index);
00358           pkt_ptr->vip_pkt_3way_req.net_local_vi_index =
00359             VIP_HTON_UINT16 (vip_vi_ptr->index);
00360 
00361           vip_send_req_ptr->type |= VIP_SEND_REQ_RELIABLE;
00362           vip_send_req_ptr->dest_port_id = vip_vi_ptr->gm_dest_port;
00363           vip_send_req_ptr->dest_gm_id = vip_vi_ptr->gm_dest_id;
00364           vip_send_req_ptr->vip_nic_ptr = vip_nic_ptr;
00365           vip_send_req_ptr->vip_vi_ptr = vip_vi_ptr;
00366           vip_send_data (vip_send_req_ptr);
00367         }
00368     }
00369   else
00370     {
00371       vip_desc_ptr->CS.Status |= VIP_STATUS_OP_RDMA_WRITE;
00372 
00373       /* check the Reserved part of the address segment */
00374       if (vip_desc_ptr->DS[0].Remote.Reserved != 0)
00375         {
00376           VIP_DEBUG (("Reserved part of the Address segment is not null"));
00377           vip_desc_ptr->CS.Status |= VIP_STATUS_FORMAT_ERROR;
00378           goto out_with_sync_error;
00379         }
00380 
00381       /* immediate data ? */
00382       if ((vip_desc_ptr->CS.Control & VIP_CONTROL_IMMEDIATE) != 0)
00383         {
00384           VIP_DEBUG (("RDMA write with immediate (desc=%p)", vip_desc_ptr));
00385           i = sizeof (VIP_UINT32);
00386 
00387           /* allocate put req immediate packet */
00388           vip_send_req_ptr =
00389             vip_allocate_packet (vip_gm_ptr, sizeof (VIP_PACKET_PUT_REQ_IMM));
00390           VIP_ASSERT (vip_send_req_ptr != NULL);
00391           pkt_ptr = (VIP_PACKET *) (vip_send_req_ptr->ptr);
00392           VIP_FILL_GENERIC_HEAD (pkt_ptr, total_length, vip_vi_ptr,
00393                                  VIP_PUT_REQ_IMM_PKT);
00394           ((VIP_PACKET_PUT_REQ_IMM *) pkt_ptr)->net_imm_data =
00395             VIP_HTON_UINT32(vip_desc_ptr->CS.ImmediateData);
00396 
00397           pkt_ptr->vip_pkt_put_req.net_remote_buf =
00398             VIP_HTON_UINT64 (vip_desc_ptr->DS[0].Remote.Data.AddressBits);
00399           pkt_ptr->vip_pkt_put_req.net_remote_mem =
00400             VIP_HTON_UINT32 (vip_desc_ptr->DS[0].Remote.Handle);
00401           pkt_ptr->vip_pkt_put_req.net_local_nic_index =
00402             VIP_HTON_UINT16 (vip_nic_ptr->index);
00403           pkt_ptr->vip_pkt_put_req.net_local_vi_index =
00404             VIP_HTON_UINT16 (vip_vi_ptr->index);
00405           
00406           *(VIP_NET_UINT32*) (((VIP_UINTPTR) pkt_ptr)
00407                                + sizeof (VIP_PACKET_PUT_REQ)) =
00408             VIP_HTON_UINT32(vip_desc_ptr->CS.ImmediateData);
00409           
00410           vip_send_req_ptr->type |= VIP_SEND_REQ_RELIABLE;
00411           vip_send_req_ptr->dest_port_id = vip_vi_ptr->gm_dest_port;
00412           vip_send_req_ptr->dest_gm_id = vip_vi_ptr->gm_dest_id;
00413           vip_send_req_ptr->vip_nic_ptr = vip_nic_ptr;
00414           vip_send_req_ptr->vip_vi_ptr = vip_vi_ptr;
00415           vip_send_data (vip_send_req_ptr);
00416         }
00417       else
00418         {
00419           VIP_DEBUG (("RDMA write (desc=%p)", vip_desc_ptr));
00420 
00421 #ifndef VI_GM_FAST_RDMA
00422           /* allocate put req packet */
00423           vip_send_req_ptr =
00424             vip_allocate_packet (vip_gm_ptr, sizeof (VIP_PACKET_PUT_REQ));
00425           VIP_ASSERT (vip_send_req_ptr != NULL);
00426           pkt_ptr = (VIP_PACKET *) (vip_send_req_ptr->ptr);
00427           VIP_FILL_GENERIC_HEAD (pkt_ptr, total_length, vip_vi_ptr,
00428                                  VIP_PUT_REQ_PKT);
00429 
00430           pkt_ptr->vip_pkt_put_req.net_remote_buf =
00431             VIP_HTON_UINT64 (vip_desc_ptr->DS[0].Remote.Data.AddressBits);
00432           pkt_ptr->vip_pkt_put_req.net_remote_mem =
00433             VIP_HTON_UINT32 (vip_desc_ptr->DS[0].Remote.Handle);
00434           pkt_ptr->vip_pkt_put_req.net_local_nic_index =
00435             VIP_HTON_UINT16 (vip_nic_ptr->index);
00436           pkt_ptr->vip_pkt_put_req.net_local_vi_index =
00437             VIP_HTON_UINT16 (vip_vi_ptr->index);
00438           
00439           vip_send_req_ptr->type |= VIP_SEND_REQ_RELIABLE;
00440           vip_send_req_ptr->dest_port_id = vip_vi_ptr->gm_dest_port;
00441           vip_send_req_ptr->dest_gm_id = vip_vi_ptr->gm_dest_id;
00442           vip_send_req_ptr->vip_nic_ptr = vip_nic_ptr;
00443           vip_send_req_ptr->vip_vi_ptr = vip_vi_ptr;
00444           vip_send_data (vip_send_req_ptr);
00445 #endif
00446         }
00447 
00448 #ifdef VI_GM_FAST_RDMA
00449 
00450       /* post a Directed Send for each segment */
00451       total_length = 0;
00452       target_ptr = vip_desc_ptr->DS[0].Remote.Data;
00453       for (i = 1; i < vip_desc_ptr->CS.SegCount; i++) {
00454         if (vip_desc_ptr->DS[i].Local.Length > 0) {
00455           vip_send_req_ptr = vip_allocate_packet (vip_gm_ptr, 0);
00456           VIP_ASSERT (vip_send_req_ptr != NULL);
00457           vip_send_req_ptr->type |= VIP_SEND_REQ_RDMA_WRITE;
00458           vip_send_req_ptr->dest_port_id = vip_vi_ptr->gm_dest_port;
00459           vip_send_req_ptr->dest_gm_id = vip_vi_ptr->gm_dest_id;
00460           vip_send_req_ptr->length = vip_desc_ptr->DS[i].Local.Length;
00461           vip_send_req_ptr->target_ptr = target_ptr;
00462           vip_send_req_ptr->ptr = vip_desc_ptr->DS[i].Local.Data.Address;
00463           vip_send_req_ptr->vip_nic_ptr = vip_nic_ptr;
00464           vip_send_req_ptr->vip_vi_ptr = vip_vi_ptr;
00465           vip_send_data (vip_send_req_ptr);
00466           
00467           total_length += vip_desc_ptr->DS[i].Local.Length;
00468           target_ptr.AddressBits += vip_desc_ptr->DS[i].Local.Length;
00469         }
00470       }
00471 
00472       if (((vip_desc_ptr->CS.Control & VIP_CONTROL_IMMEDIATE) != 0) 
00473           && (vip_vi_ptr->reliability == VIP_SERVICE_RELIABLE_RECEPTION)) {
00474         /* allocate put done packet */
00475         vip_send_req_ptr = vip_allocate_packet (vip_gm_ptr,
00476                                                 sizeof (VIP_PACKET_PUT_DONE));
00477         VIP_ASSERT (vip_send_req_ptr != NULL);
00478         pkt_ptr = (VIP_PACKET *) (vip_send_req_ptr->ptr);
00479         if ((vip_desc_ptr->CS.Control & VIP_CONTROL_IMMEDIATE) != 0)
00480           {
00481             VIP_FILL_GENERIC_HEAD (pkt_ptr, total_length, vip_vi_ptr,
00482                                    VIP_PUT_DONE_IMM_PKT);
00483           }
00484         else
00485           {
00486             VIP_FILL_GENERIC_HEAD (pkt_ptr, total_length, vip_vi_ptr,
00487                                    VIP_PUT_DONE_PKT);
00488           }
00489         
00490         pkt_ptr->vip_pkt_put_done.net_local_nic_index =
00491           VIP_HTON_UINT16 (vip_nic_ptr->index);
00492         pkt_ptr->vip_pkt_put_done.net_local_vi_index =
00493           VIP_HTON_UINT16 (vip_vi_ptr->index);
00494         
00495         vip_send_req_ptr->type |= VIP_SEND_REQ_RELIABLE;
00496         vip_send_req_ptr->dest_port_id = vip_vi_ptr->gm_dest_port;
00497         vip_send_req_ptr->dest_gm_id = vip_vi_ptr->gm_dest_id;
00498         vip_send_req_ptr->vip_nic_ptr = vip_nic_ptr;
00499         vip_send_req_ptr->vip_vi_ptr = vip_vi_ptr;
00500         vip_send_req_ptr->vip_desc_ptr = vip_desc_ptr;
00501         vip_send_data (vip_send_req_ptr);
00502       } else {
00503         vip_send_req_ptr = vip_allocate_packet (vip_gm_ptr, 0);
00504         VIP_ASSERT (vip_send_req_ptr != NULL);
00505         vip_send_req_ptr->type |= VIP_SEND_REQ_RDMA_WRITE;
00506         vip_send_req_ptr->dest_port_id = vip_vi_ptr->gm_dest_port;
00507         vip_send_req_ptr->dest_gm_id = vip_vi_ptr->gm_dest_id;
00508         vip_send_req_ptr->length = 1;
00509         vip_send_req_ptr->target_ptr = vip_desc_ptr->DS[0].Remote.Data;
00510         vip_send_req_ptr->ptr = vip_desc_ptr->DS[1].Local.Data.Address;
00511         vip_send_req_ptr->vip_nic_ptr = vip_nic_ptr;
00512         vip_send_req_ptr->vip_vi_ptr = vip_vi_ptr;
00513         vip_send_req_ptr->vip_desc_ptr = vip_desc_ptr;
00514         vip_send_data (vip_send_req_ptr); 
00515       }
00516 #endif
00517       
00518     }
00519   VIP_DEBUG (("Success"));
00520   return;
00521 
00522 out_with_sync_error:
00523   /* complete the current descriptor */
00524   vip_notify_desc_completion (vip_desc_ptr, vip_vi_ptr, VIP_FALSE);
00525   VIP_DEBUG (("Synchronous error"));
00526   if ((vip_vi_ptr->reliability != VIP_SERVICE_UNRELIABLE)
00527       && (vip_vi_ptr->state != VIP_STATE_ERROR))
00528     {
00529       /* the VI transition to error state */
00530       vip_vi_transition_to_error_state (vip_vi_ptr, VIP_TRUE);
00531 
00532       /* a connection lost asynchronous error is generated */
00533       vip_generate_async_error (vip_nic_ptr, vip_vi_ptr, NULL, NULL,
00534                                 VIP_RESOURCE_VI, VIP_ERROR_CONN_LOST, 0);
00535     }
00536   else
00537     {
00538       /* shift to the next send descriptor */
00539       VIP_ASSERT (vip_vi_ptr->send_queue.count_to_process > 0);
00540       vip_vi_ptr->send_queue.count_to_process--;
00541       vip_vi_ptr->send_queue.current_desc = vip_desc_ptr->CS.Next.Address;
00542       vip_vi_ptr->send_queue.current_mem = vip_desc_ptr->CS.NextHandle;
00543 
00544       /* process next descriptor */
00545       if (vip_vi_ptr->send_queue.count_to_process > 0)
00546         {
00547           vip_process_send_desc (vip_vi_ptr);
00548         }
00549     }
00550   return;
00551 
00552 async_post_desc_error:
00553   /* generate an asynchronous error */
00554   vip_generate_async_error (vip_nic_ptr, vip_vi_ptr, NULL, vip_desc_ptr,
00555                             VIP_RESOURCE_DESCRIPTOR, VIP_ERROR_POST_DESC, 0);
00556 
00557   if (vip_vi_ptr->state != VIP_STATE_ERROR)
00558     {
00559       /* the VI transition to error state */
00560       vip_vi_transition_to_error_state (vip_vi_ptr, VIP_TRUE);
00561 
00562       /* a connection lost asynchronous error is generated */
00563       vip_generate_async_error (vip_nic_ptr, vip_vi_ptr, NULL, NULL,
00564                                 VIP_RESOURCE_VI, VIP_ERROR_CONN_LOST, 0);
00565     }
00566 
00567   VIP_DEBUG (("Asynchronous error"));
00568   return;
00569 }
00570 
00587 VIP_SEND_REQ *
00588 vip_allocate_packet (VIP_GM * vip_gm_ptr, VIP_UINT32 length)
00589 {
00590   VIP_SEND_REQ *vip_send_req_ptr;
00591   VIP_DEBUG_LABEL (("vip_allocate_packet"));
00592 
00593   VIP_ASSERT (vip_gm_ptr != NULL);
00594   VIP_ASSERT (length <= VI_GM_EAGER_LENGTH);
00595   VIP_ASSERT_MUTEX_LOCKED (&(vip_gm_ptr->lock));
00596 
00597   vip_send_req_ptr =
00598     (VIP_SEND_REQ *) gm_lookaside_alloc (vip_gm_ptr->vip_send_req_lookaside);
00599   if (vip_send_req_ptr == NULL)
00600     {
00601       VIP_DEBUG (("Error allocating send request"));
00602       return NULL;
00603     }
00604 
00605   if (length > 0)
00606     {
00607       if (vip_gm_ptr->send_buffers_free != NULL)
00608         {
00609           VIP_ASSERT (vip_gm_ptr->send_buf_free_cnt > 0);
00610           vip_send_req_ptr->ptr = vip_gm_ptr->send_buffers_free;
00611           vip_gm_ptr->send_buffers_free =
00612             *((VIP_PVOID *) (vip_gm_ptr->send_buffers_free));
00613           vip_send_req_ptr->type = VIP_SEND_REQ_DMA;
00614           vip_gm_ptr->send_buf_free_cnt--;
00615         }
00616       else
00617         {
00618           VIP_ASSERT (vip_gm_ptr->send_buf_free_cnt == 0);
00619           vip_send_req_ptr->ptr = malloc (length);
00620           if (vip_send_req_ptr->ptr == NULL)
00621             {
00622               VIP_DEBUG (("Not enough memory, malloc failed"));
00623               gm_lookaside_free (vip_send_req_ptr);
00624               return NULL;
00625             }
00626           vip_send_req_ptr->type = VIP_SEND_REQ_MALLOC;
00627         }
00628     }
00629   else
00630     {
00631       vip_send_req_ptr->ptr = NULL;
00632       vip_send_req_ptr->type = VIP_SEND_REQ_NONE;
00633     }
00634 
00635   vip_send_req_ptr->dest_port_id = 0;
00636   vip_send_req_ptr->dest_gm_id = 0;
00637   vip_send_req_ptr->length = length;
00638   vip_send_req_ptr->target_ptr.AddressBits = 0;
00639   vip_send_req_ptr->vip_gm_ptr = vip_gm_ptr;
00640   vip_send_req_ptr->vip_nic_ptr = NULL;
00641   vip_send_req_ptr->vip_vi_ptr = NULL;
00642   vip_send_req_ptr->vip_desc_ptr = NULL;
00643   vip_send_req_ptr->next = NULL;
00644 
00645   VIP_DEBUG (("Success"));
00646   return vip_send_req_ptr;
00647 }
00648 
00661 void
00662 vip_send_data (VIP_SEND_REQ * vip_send_req_ptr)
00663 {
00664   VIP_GM *vip_gm_ptr;
00665   VIP_PVOID pkt;
00666   VIP_DEBUG_LABEL (("vip_send_data"));
00667 
00668   VIP_ASSERT (vip_send_req_ptr != NULL);
00669   VIP_ASSERT (vip_send_req_ptr->type > 0);
00670   VIP_ASSERT (vip_send_req_ptr->dest_port_id > 0);
00671   VIP_ASSERT (vip_send_req_ptr->dest_gm_id > 0);
00672   VIP_ASSERT (vip_send_req_ptr->length > 0);
00673   VIP_ASSERT (vip_send_req_ptr->ptr != NULL);
00674   VIP_ASSERT (vip_send_req_ptr->vip_gm_ptr != NULL);
00675 
00676   pkt = vip_send_req_ptr->ptr;
00677   vip_gm_ptr = vip_send_req_ptr->vip_gm_ptr;
00678   VIP_ASSERT_MUTEX_LOCKED (&(vip_gm_ptr->lock));
00679 
00680   if ((vip_gm_ptr->send_fifo_head == NULL)
00681       && ((vip_send_req_ptr->type & VIP_SEND_REQ_MALLOC) == 0)
00682       && (vip_gm_ptr->send_tokens > 0))
00683     {
00684       VIP_ASSERT (vip_gm_ptr->send_fifo_head == NULL);
00685       VIP_ASSERT (vip_gm_ptr->send_fifo_tail == NULL);
00686       VIP_ASSERT (vip_gm_ptr->send_fifo_queued == 0);
00687 
00688       switch ((vip_send_req_ptr->type) & VIP_SEND_REQ_OPMASK)
00689         {
00690         case VIP_SEND_REQ_RELIABLE:
00691           VIP_ASSERT ((vip_send_req_ptr->type & VIP_SEND_REQ_NONE) == 0);
00692           VIP_ASSERT (vip_send_req_ptr->target_ptr.Address == NULL);
00693           /*  VI_GM_DEBUG_CHECKSUM_COMPUTE */
00694           /*        ((VIP_CHKSUM *) pkt, */
00695           /*         (void *) ((VIP_UINTPTR) pkt + sizeof (VIP_CHKSUM)), */
00696           /*         vip_send_req_ptr->length - sizeof (VIP_CHKSUM)); */
00697 
00698           gm_send_with_callback (vip_gm_ptr->gm_port, pkt,
00699                                  VI_GM_CTRL_GM_SIZE,
00700                                  vip_send_req_ptr->length,
00701                                  GM_LOW_PRIORITY,
00702                                  vip_send_req_ptr->dest_gm_id,
00703                                  vip_send_req_ptr->dest_port_id,
00704                                  vip_sent_callback, vip_send_req_ptr);
00705           VIP_DEBUG (("Reliable packet sent immediately"));
00706           break;
00707 
00708         case VIP_SEND_REQ_UNRELIABLE:
00709           VIP_ASSERT (vip_send_req_ptr->length
00710                       <= gm_mtu (vip_gm_ptr->gm_port));
00711           VIP_ASSERT (vip_send_req_ptr->vip_vi_ptr != NULL);
00712           VIP_ASSERT (vip_send_req_ptr->vip_vi_ptr->reliability
00713                       == VIP_SERVICE_UNRELIABLE);
00714           VIP_ASSERT ((vip_send_req_ptr->type & VIP_SEND_REQ_NONE) == 0);
00715           VIP_ASSERT (vip_send_req_ptr->target_ptr.Address == NULL);
00716 
00717           /*  VI_GM_DEBUG_CHECKSUM_COMPUTE */
00718           /*        ((VIP_CHKSUM *) pkt, */
00719           /*         (void *) ((VIP_UINTPTR) pkt + sizeof (VIP_CHKSUM)), */
00720           /*         vip_send_req_ptr->length - sizeof (VIP_CHKSUM)); */
00721 
00722           gm_datagram_send (vip_gm_ptr->gm_port, pkt,
00723                             VI_GM_CTRL_GM_SIZE,
00724                             vip_send_req_ptr->length,
00725                             GM_LOW_PRIORITY,
00726                             vip_send_req_ptr->dest_gm_id,
00727                             vip_send_req_ptr->dest_port_id,
00728                             vip_sent_callback, vip_send_req_ptr);
00729           VIP_DEBUG (("Unreliable packet sent immediately"));
00730           break;
00731 
00732         case VIP_SEND_REQ_RDMA_WRITE:
00733           VIP_ASSERT ((vip_send_req_ptr->type & VIP_SEND_REQ_NONE) != 0);
00734           VIP_ASSERT (vip_send_req_ptr->vip_vi_ptr != NULL);
00735           VIP_ASSERT (vip_send_req_ptr->target_ptr.Address != NULL);
00736           
00737           gm_directed_send_with_callback
00738             (vip_gm_ptr->gm_port, pkt,
00739              (gm_remote_ptr_t) (vip_send_req_ptr->target_ptr.AddressBits),
00740              vip_send_req_ptr->length,
00741              GM_LOW_PRIORITY,
00742              vip_send_req_ptr->dest_gm_id,
00743              vip_send_req_ptr->dest_port_id,
00744              vip_sent_callback, vip_send_req_ptr);
00745           VIP_DEBUG (("RDMA PUT packet sent immediately"));
00746           break;
00747 
00748         default:
00749           VIP_ABORT (("Invalid operation type in send request"));
00750         }
00751 
00752       vip_gm_ptr->send_tokens--;
00753       if ((vip_send_req_ptr->vip_vi_ptr != NULL) 
00754           && (vip_send_req_ptr->vip_desc_ptr != NULL))
00755         {
00756           vip_send_req_ptr->vip_vi_ptr->pending_callbacks++;
00757         }
00758     }
00759   else
00760     {
00761       if (vip_gm_ptr->send_fifo_head == NULL)
00762         {
00763           VIP_ASSERT (vip_gm_ptr->send_fifo_tail == NULL);
00764           VIP_ASSERT (vip_gm_ptr->send_fifo_queued == 0);
00765           vip_gm_ptr->send_fifo_head = vip_send_req_ptr;
00766         }
00767       else
00768         {
00769           VIP_ASSERT (vip_gm_ptr->send_fifo_tail->next == NULL);
00770           vip_gm_ptr->send_fifo_tail->next = vip_send_req_ptr;
00771         }
00772 
00773       vip_gm_ptr->send_fifo_tail = vip_send_req_ptr;
00774       vip_send_req_ptr->next = NULL;
00775       vip_gm_ptr->send_fifo_queued++;
00776       VIP_DEBUG (("Packet queued in the send FIFO"));
00777     }
00778 
00779   VIP_DEBUG (("Success"));
00780 }
00781 
00794 static void
00795 vip_flush_fifo_send (VIP_GM * vip_gm_ptr)
00796 {
00797   VIP_SEND_REQ *vip_send_req_ptr;
00798   VIP_PVOID pkt;
00799   VIP_DEBUG_LABEL (("vip_flush_fifo_send"));
00800 
00801   VIP_ASSERT_MUTEX_LOCKED (&(vip_gm_ptr->lock));
00802   VIP_ASSERT_MUTEX_LOCKED (&(vip_nic_ptr->lock));
00803 
00804   while ((vip_gm_ptr->send_fifo_head != NULL)
00805          && (vip_gm_ptr->send_tokens > 0))
00806     {
00807       VIP_ASSERT (vip_gm_ptr->send_fifo_queued > 0);
00808       vip_send_req_ptr = vip_gm_ptr->send_fifo_head;
00809 
00810       if ((vip_send_req_ptr->type & VIP_SEND_REQ_MALLOC) != 0)
00811         {
00812           if (vip_gm_ptr->send_buffers_free == NULL)
00813             {
00814               VIP_ASSERT (vip_gm_ptr->send_buf_free_cnt == 0);
00815               return;
00816             }
00817           else
00818             {
00819               VIP_ASSERT (vip_gm_ptr->send_buffers_free != NULL);
00820               VIP_ASSERT (vip_gm_ptr->send_buf_free_cnt > 0);
00821               VIP_ASSERT (vip_send_req_ptr->length > 0);
00822               VIP_ASSERT (vip_send_req_ptr->ptr != NULL);
00823               VIP_ASSERT (vip_send_req_ptr->vip_gm_ptr != NULL);
00824 
00825               pkt = vip_gm_ptr->send_buffers_free;
00826               vip_gm_ptr->send_buffers_free =
00827                 *((VIP_PVOID *) (vip_gm_ptr->send_buffers_free));
00828               memcpy (pkt, vip_send_req_ptr->ptr, vip_send_req_ptr->length);
00829               free (vip_send_req_ptr->ptr);
00830               vip_send_req_ptr->type |= ~VIP_SEND_REQ_MALLOC;
00831               vip_send_req_ptr->type |= VIP_SEND_REQ_DMA;
00832               vip_send_req_ptr->ptr = pkt;
00833               vip_gm_ptr->send_buf_free_cnt--;
00834             }
00835         }
00836 
00837       pkt = vip_send_req_ptr->ptr;
00838       switch ((vip_send_req_ptr->type) & VIP_SEND_REQ_OPMASK)
00839         {
00840         case VIP_SEND_REQ_RELIABLE:
00841           VIP_ASSERT ((vip_send_req_ptr->type & VIP_SEND_REQ_NONE) == 0);
00842           VIP_ASSERT (vip_send_req_ptr->target_ptr.Address == NULL);
00843           /*  VI_GM_DEBUG_CHECKSUM_COMPUTE */
00844           /*        ((VIP_CHKSUM *) pkt, */
00845           /*         (void *) ((VIP_UINTPTR) pkt + sizeof (VIP_CHKSUM)), */
00846           /*         vip_send_req_ptr->length - sizeof (VIP_CHKSUM)); */
00847 
00848           gm_send_with_callback (vip_gm_ptr->gm_port, pkt,
00849                                  VI_GM_CTRL_GM_SIZE,
00850                                  vip_send_req_ptr->length,
00851                                  GM_LOW_PRIORITY,
00852                                  vip_send_req_ptr->dest_gm_id,
00853                                  vip_send_req_ptr->dest_port_id,
00854                                  vip_sent_callback, vip_send_req_ptr);
00855           VIP_DEBUG (("Reliable packet sent from FIFO"));
00856           break;
00857 
00858         case VIP_SEND_REQ_UNRELIABLE:
00859           VIP_ASSERT (vip_send_req_ptr->length
00860                       <= gm_mtu (vip_gm_ptr->gm_port));
00861           VIP_ASSERT (vip_send_req_ptr->vip_vi_ptr != NULL);
00862           VIP_ASSERT (vip_send_req_ptr->vip_vi_ptr->reliability
00863                       == VIP_SERVICE_UNRELIABLE);
00864           VIP_ASSERT ((vip_send_req_ptr->type & VIP_SEND_REQ_NONE) == 0);
00865           VIP_ASSERT (vip_send_req_ptr->target_ptr.Address == NULL);
00866 
00867           /* VI_GM_DEBUG_CHECKSUM_COMPUTE */
00868           /*        ((VIP_CHKSUM *) pkt, */
00869           /*         (void *) ((VIP_UINTPTR) pkt + sizeof (VIP_CHKSUM)), */
00870           /*         vip_send_req_ptr->length - sizeof (VIP_CHKSUM)); */
00871 
00872           gm_datagram_send (vip_gm_ptr->gm_port, pkt,
00873                             VI_GM_CTRL_GM_SIZE,
00874                             vip_send_req_ptr->length,
00875                             GM_LOW_PRIORITY,
00876                             vip_send_req_ptr->dest_gm_id,
00877                             vip_send_req_ptr->dest_port_id,
00878                             vip_sent_callback, vip_send_req_ptr);
00879           VIP_DEBUG (("Unreliable packet sent from FIFO"));
00880           break;
00881 
00882         case VIP_SEND_REQ_RDMA_WRITE:
00883           VIP_ASSERT ((vip_send_req_ptr->type & VIP_SEND_REQ_NONE) != 0);
00884           VIP_ASSERT (vip_send_req_ptr->vip_vi_ptr != NULL);
00885           VIP_ASSERT (vip_send_req_ptr->target_ptr.Address != NULL);
00886           
00887           gm_directed_send_with_callback
00888             (vip_gm_ptr->gm_port, pkt,
00889              (gm_remote_ptr_t) (vip_send_req_ptr->target_ptr.AddressBits),
00890              vip_send_req_ptr->length,
00891              GM_LOW_PRIORITY,
00892              vip_send_req_ptr->dest_gm_id,
00893              vip_send_req_ptr->dest_port_id,
00894              vip_sent_callback, vip_send_req_ptr);
00895           VIP_DEBUG (("RDMA PUT packet sent from FIFO"));
00896           break;
00897 
00898         default:
00899           VIP_ABORT (("Invalid operation type in send request"));
00900         }
00901 
00902       vip_gm_ptr->send_tokens--;
00903       vip_gm_ptr->send_fifo_queued--;
00904       vip_gm_ptr->send_fifo_head = vip_send_req_ptr->next;
00905       if ((vip_send_req_ptr->vip_vi_ptr != NULL)
00906           && (vip_send_req_ptr->vip_desc_ptr != NULL))
00907         {
00908           vip_send_req_ptr->vip_vi_ptr->pending_callbacks++;
00909         }
00910 
00911       if (vip_gm_ptr->send_fifo_head == NULL)
00912         {
00913           VIP_ASSERT (vip_gm_ptr->send_fifo_tail == vip_send_req_ptr);
00914           VIP_ASSERT (vip_gm_ptr->send_fifo_queued == 0);
00915           vip_gm_ptr->send_fifo_tail = NULL;
00916         }
00917     }
00918 }
00919 
00932 static void
00933 vip_sent_report_callback_status (VIP_SEND_REQ * vip_send_req_ptr,
00934                                  gm_status_t status)
00935 {
00936   VIP_GM *vip_gm_ptr;
00937   VIP_DEBUG_LABEL (("Error"));
00938 
00939 #if VI_GM_CATASTROPHIC_ERROR_VERBOSE
00940 
00941   vip_gm_ptr = vip_send_req_ptr->vip_gm_ptr;
00942   VIP_DEBUG_PROTECTED (("GM send operation from %s (port %d)"
00943                         " to %s (port %d%s) returned the error %u <%s>.\n",
00944                         gm_node_id_to_host_name (vip_gm_ptr->gm_port,
00945                                                  vip_gm_ptr->gm_id),
00946                         vip_gm_ptr->gm_port_id,
00947                         gm_node_id_to_host_name (vip_gm_ptr->gm_port,
00948                                                  vip_send_req_ptr->dest_gm_id),
00949                         vip_send_req_ptr->dest_port_id,
00950                         ((vip_send_req_ptr->dest_port_id
00951                           == VI_GM_PORT_CONN_MANAGER)
00952                          ? ", Connection Manager" : ""), status,
00953                         gm_strerror (status)));
00954 
00955 #else
00956 
00957   VIP_DEBUG (("Send completion error, message to GM id %d / port %d (%s)\n",
00958               vip_send_req_ptr->dest_gm_id, vip_send_req_ptr->dest_port_id,
00959               gm_strerror (status)));
00960 
00961 #endif
00962 }
00963 
00964 
00980 static void
00981 vip_resume_callback (struct gm_port *port, void *context, gm_status_t status)
00982 {
00983   VIP_GM *vip_gm_ptr;
00984   VIP_VI *vip_vi_ptr;
00985   VIP_SEND_REQ *vip_send_req_ptr;
00986   VIP_DESCRIPTOR *vip_desc_ptr;
00987   VIP_DEBUG_LABEL (("vip_resume_callback"));
00988 
00989   VIP_ASSERT (context != NULL);
00990   vip_send_req_ptr = (VIP_SEND_REQ *) context;
00991   vip_gm_ptr = vip_send_req_ptr->vip_gm_ptr;
00992   vip_vi_ptr = vip_send_req_ptr->vip_vi_ptr;
00993   VIP_ASSERT (vip_gm_ptr != NULL);
00994   VIP_ASSERT_MUTEX_LOCKED (&(vip_gm_ptr->lock));
00995 
00996   VIP_DEBUG (("Resume sending to GM id %d / port %d\n",
00997               vip_send_req_ptr->dest_gm_id, vip_send_req_ptr->dest_port_id));
00998   
00999   vip_desc_ptr = vip_send_req_ptr->vip_desc_ptr;
01000   if (vip_send_req_ptr->vip_nic_ptr != NULL)
01001     {
01002       if (VIP_INVALID_NIC_HANDLE (vip_send_req_ptr->vip_nic_ptr))
01003         {
01004           VIP_DEBUG (("Invalid NIC handle in send descriptor"));
01005           goto resume_recycle;
01006         }
01007       
01008       VIP_MUTEX_LOCK (&(vip_send_req_ptr->vip_nic_ptr->lock));
01009       if (vip_desc_ptr != NULL)
01010         {
01011           vip_generate_async_error 
01012             (vip_send_req_ptr->vip_nic_ptr, vip_vi_ptr, NULL, 
01013              vip_desc_ptr, VIP_RESOURCE_NIC, VIP_ERROR_CATASTROPHIC,
01014              (vip_desc_ptr->CS.Status & VIP_STATUS_OP_MASK));
01015         }
01016       else
01017         {
01018           if (vip_vi_ptr->state != VIP_STATE_CONNECT_PENDING)
01019             {
01020               vip_generate_async_error 
01021                 (vip_send_req_ptr->vip_nic_ptr, vip_vi_ptr, NULL, 
01022                  vip_desc_ptr, VIP_RESOURCE_NIC, VIP_ERROR_CATASTROPHIC, 0);
01023             }
01024         }
01025       
01026       if (vip_vi_ptr != NULL)
01027         {
01028           /* complete the pending send if needed */
01029           if (vip_desc_ptr != NULL)
01030             {
01031               VIP_ASSERT (vip_vi_ptr->pending_callbacks > 0);
01032               vip_vi_ptr->pending_callbacks--;
01033               
01034               vip_desc_ptr->CS.Status |= VIP_STATUS_TRANSPORT_ERROR;
01035               vip_notify_desc_completion (vip_desc_ptr, vip_vi_ptr,
01036                                           VIP_FALSE);
01037           
01038               if (vip_vi_ptr->reliability != VIP_SERVICE_UNRELIABLE)
01039                 {
01040                   /* shift to the next send descriptor */
01041                   if (vip_vi_ptr->send_queue.count_to_process > 0)
01042                     {
01043                       vip_vi_ptr->send_queue.count_to_process--;
01044                       vip_vi_ptr->send_queue.current_desc =
01045                         vip_desc_ptr->CS.Next.Address;
01046                       vip_vi_ptr->send_queue.current_mem =
01047                         vip_desc_ptr->CS.NextHandle;
01048                     }
01049 
01050                   /* process next descriptor */
01051                   if (vip_vi_ptr->send_queue.count_to_process > 0)
01052                     {
01053                       vip_process_send_desc (vip_vi_ptr);
01054                     }
01055                 }
01056             }
01057           
01058           if ((vip_vi_ptr->state != VIP_STATE_ERROR) 
01059               && (vip_vi_ptr->state != VIP_STATE_CONNECT_PENDING))
01060             {
01061               /* the VI transition to error state */
01062               vip_vi_transition_to_error_state (vip_vi_ptr, VIP_TRUE);
01063               
01064               /* a connection lost asynchronous error is generated */
01065               vip_generate_async_error (vip_send_req_ptr->vip_nic_ptr,
01066                                         vip_vi_ptr, NULL, NULL,
01067                                         VIP_RESOURCE_VI,
01068                                         VIP_ERROR_CONN_LOST, 0);
01069             }
01070         }
01071       
01072       VIP_MUTEX_UNLOCK (&(vip_send_req_ptr->vip_nic_ptr->lock));
01073     }
01074   
01075  resume_recycle:
01076   switch (vip_send_req_ptr->type & VIP_SEND_REQ_TYPEMASK)
01077     {
01078     case VIP_SEND_REQ_DMA:
01079       *((VIP_PVOID *) (vip_send_req_ptr->ptr)) =
01080         vip_gm_ptr->send_buffers_free;
01081       vip_gm_ptr->send_buffers_free = vip_send_req_ptr->ptr;
01082       vip_gm_ptr->send_buf_free_cnt++;
01083       break;
01084       
01085     case VIP_SEND_REQ_NONE:
01086       break;
01087       
01088     case VIP_SEND_REQ_MALLOC:
01089       free (vip_send_req_ptr->ptr);
01090       break;
01091 
01092     default:
01093       VIP_ABORT (("Bad send request type in resume callback"));
01094     }
01095   
01096   VIP_ASSERT (vip_gm_ptr->send_tokens <= vip_gm_ptr->max_send_tokens);
01097   vip_gm_ptr->send_tokens++;
01098   gm_lookaside_free (vip_send_req_ptr);
01099   
01100   /* flush the send FIFO */
01101   if (vip_gm_ptr->send_fifo_head != NULL)
01102     {
01103       vip_flush_fifo_send (vip_gm_ptr);
01104     }
01105 
01106   VIP_DEBUG (("Success"));
01107 }
01108      
01109 
01124 void
01125 vip_sent_callback (struct gm_port *port, void *context, gm_status_t status)
01126 {
01127   VIP_GM *vip_gm_ptr;
01128   VIP_VI *vip_vi_ptr;
01129   VIP_SEND_REQ *vip_send_req_ptr;
01130   VIP_DESCRIPTOR *vip_desc_ptr;
01131   VIP_DEBUG_LABEL (("vip_sent_callback"));
01132 
01133   VIP_ASSERT (context != NULL);
01134   vip_send_req_ptr = (VIP_SEND_REQ *) context;
01135   vip_gm_ptr = vip_send_req_ptr->vip_gm_ptr;
01136   vip_vi_ptr = vip_send_req_ptr->vip_vi_ptr;
01137   VIP_ASSERT (vip_gm_ptr != NULL);
01138   VIP_ASSERT_MUTEX_LOCKED (&(vip_gm_ptr->lock));
01139 
01140   vip_desc_ptr = vip_send_req_ptr->vip_desc_ptr;
01141   if (status == GM_SUCCESS)
01142     {
01143       if (vip_desc_ptr != NULL)
01144         {
01145           if (VIP_INVALID_NIC_HANDLE (vip_send_req_ptr->vip_nic_ptr))
01146             {
01147               VIP_DEBUG (("Invalid NIC handle in send descriptor"));
01148               goto sent_recycle;
01149             }
01150 
01151           VIP_MUTEX_LOCK (&(vip_send_req_ptr->vip_nic_ptr->lock));
01152           if (VIP_INVALID_VI_HANDLE (vip_vi_ptr))
01153             {
01154               VIP_ABORT (("Invalid VI handle in send descriptor"));
01155             }
01156           
01157           VIP_ASSERT (vip_vi_ptr->pending_callbacks > 0);
01158           vip_vi_ptr->pending_callbacks--;
01159 
01160           /* notify the descriptor completion to the VI if not RR */
01161           if (vip_vi_ptr->reliability != VIP_SERVICE_RELIABLE_RECEPTION)
01162             {
01163               vip_notify_desc_completion (vip_desc_ptr, vip_vi_ptr,
01164                                           VIP_FALSE);
01165 
01166               /* shift to the next send descriptor */
01167               VIP_ASSERT (vip_vi_ptr->send_queue.count_to_process > 0);
01168               vip_vi_ptr->send_queue.count_to_process--;
01169               vip_vi_ptr->send_queue.current_desc =
01170                 vip_desc_ptr->CS.Next.Address;
01171               vip_vi_ptr->send_queue.current_mem =
01172                 vip_desc_ptr->CS.NextHandle;
01173 
01174               /* process next descriptor */
01175               if (vip_vi_ptr->send_queue.count_to_process > 0)
01176                 {
01177                   vip_process_send_desc (vip_vi_ptr);
01178                 }
01179             }
01180           VIP_MUTEX_UNLOCK (&(vip_send_req_ptr->vip_nic_ptr->lock));
01181         }
01182     }
01183   else
01184     {
01185       vip_sent_report_callback_status (vip_send_req_ptr, status);
01186       gm_resume_sending (port, GM_LOW_PRIORITY, 
01187                          vip_send_req_ptr->dest_gm_id,
01188                          vip_send_req_ptr->dest_port_id,
01189                          vip_resume_callback, context);
01190       VIP_DEBUG (("Resuming sending"));
01191       return;
01192     }
01193   
01194  sent_recycle:
01195   switch (vip_send_req_ptr->type & VIP_SEND_REQ_TYPEMASK)
01196     {
01197     case VIP_SEND_REQ_DMA:
01198       *((VIP_PVOID *) (vip_send_req_ptr->ptr)) =
01199         vip_gm_ptr->send_buffers_free;
01200       vip_gm_ptr->send_buffers_free = vip_send_req_ptr->ptr;
01201       vip_gm_ptr->send_buf_free_cnt++;
01202       break;
01203       
01204     case VIP_SEND_REQ_NONE:
01205       break;
01206 
01207     case VIP_SEND_REQ_MALLOC:
01208       free (vip_send_req_ptr->ptr);
01209       break;
01210 
01211     default:
01212       VIP_ABORT (("Bad send request type in send callback"));
01213     }
01214 
01215   VIP_ASSERT (vip_gm_ptr->send_tokens <= vip_gm_ptr->max_send_tokens);
01216   vip_gm_ptr->send_tokens++;
01217   gm_lookaside_free (vip_send_req_ptr);
01218 
01219   /* flush the send FIFO */
01220   if (vip_gm_ptr->send_fifo_head != NULL)
01221     {
01222       vip_flush_fifo_send (vip_gm_ptr);
01223     }
01224