[IBAL] Remove unused files.
authorftillier <ftillier@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Wed, 5 Jul 2006 14:03:48 +0000 (14:03 +0000)
committerftillier <ftillier@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Wed, 5 Jul 2006 14:03:48 +0000 (14:03 +0000)
git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@403 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

core/al/al_cm.h [deleted file]
core/al/al_cm_shared.c [deleted file]
core/al/al_cm_shared.h [deleted file]
core/al/kernel/al_cm.c [deleted file]
core/al/kernel/al_cm_conn.c [deleted file]
core/al/kernel/al_cm_sidr.c [deleted file]

diff --git a/core/al/al_cm.h b/core/al/al_cm.h
deleted file mode 100644 (file)
index 6619998..0000000
+++ /dev/null
@@ -1,721 +0,0 @@
-/*\r
- * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
- * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. \r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- *     Redistribution and use in source and binary forms, with or\r
- *     without modification, are permitted provided that the following\r
- *     conditions are met:\r
- *\r
- *      - Redistributions of source code must retain the above\r
- *        copyright notice, this list of conditions and the following\r
- *        disclaimer.\r
- *\r
- *      - Redistributions in binary form must reproduce the above\r
- *        copyright notice, this list of conditions and the following\r
- *        disclaimer in the documentation and/or other materials\r
- *        provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- * $Id$\r
- */\r
-\r
-#if !defined(__IB_AL_CM_H__)\r
-#define __IB_AL_CM_H__\r
-\r
-\r
-#include <iba/ib_al.h>\r
-#include "al_common.h"\r
-#include <complib/cl_qlist.h>\r
-#include <complib/cl_qmap.h>\r
-#include <complib/cl_qpool.h>\r
-#include <complib/cl_timer.h>\r
-#include <complib/cl_byteswap.h>\r
-#include <complib/cl_atomic.h>\r
-#include <complib/cl_pool.h>\r
-#include <complib/cl_mutex.h>\r
-#include "al_cm_conn.h"\r
-#include "al_cm_sidr.h"\r
-\r
-\r
-\r
-\r
-/* States match CM state transition diagrams from spec. */\r
-typedef enum _cm_state\r
-{\r
-       CM_CONN_RESET,\r
-       CM_CONN_IDLE,\r
-       CM_CONN_REQ_RCVD,\r
-       CM_CONN_REQ_SENT,\r
-       CM_CONN_REQ_MRA_RCVD,\r
-       CM_CONN_REQ_MRA_SENT,\r
-       CM_CONN_REP_RCVD,\r
-       CM_CONN_REP_SENT,\r
-       CM_CONN_REP_MRA_RCVD,\r
-       CM_CONN_REP_MRA_SENT,\r
-       CM_CONN_ESTABLISHED,\r
-       CM_CONN_LAP_RCVD,\r
-       CM_CONN_LAP_SENT,\r
-       CM_CONN_LAP_MRA_RCVD,\r
-       CM_CONN_LAP_MRA_SENT,\r
-       CM_CONN_DREQ_SENT,\r
-       CM_CONN_DREQ_RCVD,\r
-       CM_CONN_DREP_SENT,\r
-       CM_CONN_TIMEWAIT,\r
-       CM_CONN_CANCELING,\r
-       CM_CONN_ERROR\r
-\r
-} cm_state_t;\r
-\r
-\r
-/*\r
- * CM Structures.\r
- */\r
-typedef struct _conn_req\r
-{\r
-       uint8_t                                         class_ver;\r
-\r
-       uint8_t                                         max_cm_retries;\r
-\r
-       net64_t                                         svc_id;\r
-       uint8_t                                         *p_compare_buffer;\r
-       uint32_t                                        compare_offset;\r
-       uint32_t                                        compare_length;\r
-\r
-       /* Transport type, used for peer to peer only. */\r
-       ib_qp_type_t                            xport_type;\r
-\r
-       /* Local QP number, used for REQ. */\r
-       ib_net32_t                                      local_qpn;\r
-\r
-       /* CA attributes for primary and alternate paths. */\r
-       ib_ca_attr_t                            *p_ca_attr;\r
-       /* Primary and alternate port index. */\r
-       uint8_t                                         port_idx;\r
-       uint8_t                                         alt_port_idx;\r
-\r
-       /*\r
-        * QP Modify structures filled in using received MAD information.\r
-        * While this is less memory efficient, it makes the code cleaner\r
-        * by removing the need to copy REQ and REP data to temporary fields\r
-        * and then copying again into the qp_mod structure when performing\r
-        * QP transitions.\r
-        */\r
-       ib_qp_mod_t                                     qp_mod_rtr;\r
-       ib_qp_mod_t                                     qp_mod_rts;\r
-\r
-       /* Callbacks used for establishment */\r
-       ib_pfn_cm_req_cb_t                      pfn_cm_req_cb;\r
-       ib_pfn_cm_rep_cb_t                      pfn_cm_rep_cb;\r
-       ib_pfn_cm_rtu_cb_t                      pfn_cm_rtu_cb;\r
-\r
-       /* SIDR info */\r
-       const void                                      *sidr_context;\r
-\r
-}      conn_req_t;\r
-\r
-\r
-typedef struct _al_listen\r
-{\r
-       al_obj_t                                        obj;\r
-\r
-       cl_list_item_t                          list_item;\r
-       cl_async_proc_item_t            async_item;\r
-\r
-       ib_cm_listen_t                          info;\r
-       ib_pfn_listen_err_cb_t          pfn_err_cb;\r
-       ib_api_status_t                         err_code;\r
-\r
-}      al_listen_t;\r
-\r
-\r
-/* Per-port CM object. */\r
-typedef struct _cm_port_agent\r
-{\r
-       al_obj_t                        obj;\r
-\r
-       ib_ca_handle_t          h_ca;\r
-       ib_pd_handle_t          h_pd;\r
-       ib_qp_handle_t          h_qp;\r
-       ib_pool_key_t           pool_key;\r
-       ib_mad_svc_handle_t     h_mad_svc;\r
-\r
-       uint8_t                         port_idx;\r
-\r
-       cl_spinlock_t           lock;\r
-       cl_qlist_t                      av_list;\r
-\r
-       /* save these attributes for quick lookup without query_ca */\r
-       ib_ca_attr_t            *p_ca_attr;\r
-\r
-}      cm_port_agent_t;\r
-\r
-\r
-\r
-typedef struct _al_conn\r
-{\r
-       /* Used to store connection structure with owning AL instance. */\r
-       cl_list_item_t                          al_item;\r
-       ib_al_handle_t                          h_al;\r
-       uint64_t                                        hdl;\r
-\r
-#if defined( CL_KERNEL )\r
-       cl_mutex_t                                      mutex;\r
-#else\r
-       cl_spinlock_t                           lock;\r
-#endif\r
-\r
-       /*\r
-        * Reference count to prevent connection objects from returning\r
-        * to the pool while sends are outstanding.\r
-        */\r
-       atomic32_t                                      ref_cnt;\r
-\r
-       /* Async proc item for queueing the connection object for destruction. */\r
-       cl_async_proc_item_t            destroy_item;\r
-       /* Async proc item for processing timeouts. */\r
-       cl_async_proc_item_t            timeout_item;\r
-\r
-       /* Map item for finding connections based on local/remote comm IDs. */\r
-       cl_map_item_t                           map_item;\r
-\r
-       /* Request information stored until the connection is established. */\r
-       conn_req_t                                      *p_req_info;\r
-\r
-       /* Callbacks that can be invoked once established. */\r
-       ib_pfn_cm_mra_cb_t                      pfn_cm_mra_cb;\r
-       ib_pfn_cm_lap_cb_t                      pfn_cm_lap_cb;\r
-       ib_pfn_cm_apr_cb_t                      pfn_cm_apr_cb;\r
-       ib_pfn_cm_dreq_cb_t                     pfn_cm_dreq_cb;\r
-       ib_pfn_cm_drep_cb_t                     pfn_cm_drep_cb;\r
-       ib_pfn_cm_rej_cb_t                      pfn_cm_rej_cb; /* If RTU times out */\r
-\r
-       /* Connection type */\r
-       ib_qp_type_t                            qp_type;\r
-\r
-       /* Communication ID's for the connection. */\r
-       ib_net32_t                                      local_comm_id;\r
-       ib_net32_t                                      remote_comm_id;\r
-\r
-       ib_net64_t                                      remote_ca_guid;\r
-\r
-       /* Remote QP, used for stale connection checking. */\r
-       ib_net32_t                                      remote_qpn;\r
-\r
-       /*\r
-        * Local QP number, used for the "additional check" required\r
-        * of the DREQ.\r
-        */\r
-       ib_net32_t                                      local_qpn;\r
-\r
-       /*\r
-        * Primary and alternate path info, used to create the address vectors for\r
-        * sending MADs, to locate the port CM agent to use for outgoing sends,\r
-        * and for creating the address vectors for transitioning QPs.\r
-        */\r
-       ib_path_rec_t                           path[2];\r
-       uint8_t                                         idx_primary;\r
-\r
-       /*\r
-        * New proposed alternate path.  Need to keep this from when we\r
-        * send/receive the LAP to when we receive/send the APR and load the path.\r
-        */\r
-       ib_path_rec_t                           new_alt_path;\r
-\r
-       /* Handle to the QP for the connection. */\r
-       ib_qp_handle_t                          h_qp;\r
-\r
-       cm_state_t                                      state;\r
-\r
-       /* Timer for managing retries and timeouts for the connection object. */\r
-       cl_timer_t                                      timer;\r
-\r
-       /*\r
-        * Flag that indicates whether a connection took the active role during\r
-        * establishment.  If this flag is FALSE, the target_ack_delay field\r
-        * should be zero.\r
-        */\r
-       //***TODO: Is a target ack delay of zero valid?  If not, this flag can be\r
-       //***TODO: merged with that field, with zero indicating that the\r
-       //***TODO: connection object took the passive role.\r
-       boolean_t                                       was_active;\r
-\r
-       /*\r
-        * Handle to the sent MAD, used for cancelling. We store the handle to\r
-        * the mad service so that we can properly cancel.  This should not be a\r
-        * problem since all outstanding sends should be completed before the\r
-        * mad service completes its destruction and the handle becomes invalid.\r
-        */\r
-       ib_mad_svc_handle_t                     h_mad_svc;\r
-       ib_mad_element_t                        *p_send_mad;\r
-\r
-       /* pointer to port_cm to handle responses */\r
-       cm_port_agent_t                         *p_port_cm;\r
-\r
-       /* Maximum retries per MAD.  Set at REQ time, stored to retry LAP. */\r
-       uint8_t                                         max_cm_retries;\r
-       /* Timeout value, in milliseconds. Set at REQ time, stored to retry LAP. */\r
-       uint32_t                                        retry_timeout;\r
-\r
-       /* Given by the REP, used for alternate path setup. */\r
-       uint8_t                                         target_ack_delay;\r
-\r
-       /* Event mechanism for synchronous connection establishment. */\r
-       cl_event_t                                      *p_sync_event;\r
-\r
-       /* Cache the last MAD sent for retransmission. */\r
-       union _mads\r
-       {\r
-               ib_mad_t                                hdr;\r
-               mad_cm_req_t                    req;\r
-               mad_cm_mra_t                    mra;\r
-               mad_cm_rej_t                    rej;\r
-               mad_cm_rep_t                    rep;\r
-               mad_cm_rtu_t                    rtu;\r
-               mad_cm_dreq_t                   dreq;\r
-               mad_cm_drep_t                   drep;\r
-               mad_cm_lap_t                    lap;\r
-               mad_cm_apr_t                    apr;\r
-               mad_cm_sidr_req_t               sidr_req;\r
-               mad_cm_sidr_rep_t               sidr_rep;\r
-\r
-       }       mads;\r
-\r
-}      al_conn_t;\r
-\r
-\r
-#define CM_CONN_POOL_MIN       (100)\r
-/*\r
- * We reserve the upper byte of the connection ID as a revolving counter so\r
- * that connections that are retried by the client change connection ID.\r
- * The limit is one less than the maximum value for the lower 3-bytes because\r
- * the connection IDs start at 1.\r
- * See the IB spec, section 12.9.8.7 for details about REJ retry.\r
- */\r
-#define CM_CONN_POOL_MAX       (0x00FFFFFE)\r
-#define CM_CONN_POOL_MAX_MASK  (0x00FFFFFF)\r
-#define CM_CONN_POOL_GROW      (100)\r
-#define CM_REQ_POOL_MIN                (50)\r
-#define CM_REQ_POOL_GROW       (50)\r
-\r
-\r
-#define CM_MAD_SQ_DEPTH                                (128)\r
-#define CM_MAD_RQ_DEPTH                                (1)     /* ignored. */\r
-#define CM_MAD_SQ_SGE                          (1)\r
-#define CM_MAD_RQ_SGE                          (1)     /* ignored. */\r
-\r
-\r
-/*\r
- * Spinlock and Mutex implementations.\r
- */\r
-#if defined( CL_KERNEL )\r
-\r
-#define cm_res_init( p_res )           cl_mutex_init( &p_res->mutex )\r
-#define cm_res_destroy( p_res )                cl_mutex_destroy( &p_res->mutex )\r
-#define cm_res_acquire( p_res )                cl_mutex_acquire( &p_res->mutex )\r
-#define cm_res_release( p_res )                cl_mutex_release( &p_res->mutex )\r
-\r
-#else\r
-\r
-#define cm_res_init( p_res )           cl_spinlock_init( &p_res->lock )\r
-#define cm_res_destroy( p_res )                cl_spinlock_destroy( &p_res->lock )\r
-#define cm_res_acquire( p_res )                cl_spinlock_acquire( &p_res->lock )\r
-#define cm_res_release( p_res )                cl_spinlock_release( &p_res->lock )\r
-\r
-#endif\r
-\r
-/*\r
- * Global CM agent instance, creation, destruction.\r
- */\r
-\r
-/* Global connection manager object. */\r
-typedef struct _al_cm_agent\r
-{\r
-       al_obj_t                obj;\r
-\r
-       /* List of active listens. */\r
-       cl_qlist_t              active_listen_list;\r
-       /*\r
-        * List of listens that are in the process of being cancelled or in error.\r
-        */\r
-       cl_qlist_t              inactive_listen_list;\r
-\r
-       /* List of pending connections. */\r
-       cl_qlist_t              pending_list;\r
-       /* Map of established connections.  Key is local+remote comm ID. */\r
-       cl_qmap_t               conn_map;\r
-       /* List of connection in the time wait state. */\r
-       cl_qlist_t              time_wait_list;\r
-\r
-       cl_qpool_t              conn_pool;\r
-       cl_pool_t               req_pool;\r
-\r
-       ib_pnp_handle_t h_pnp;\r
-\r
-}      al_cm_agent_t;\r
-\r
-\r
-/*\r
- * Structure for queuing received MADs to the asynchronous processing\r
- * manager.\r
- */\r
-typedef struct _cm_async_mad\r
-{\r
-       cl_async_proc_item_t    item;\r
-       cm_port_agent_t                 *p_port_cm;\r
-       ib_mad_element_t                *p_mad;\r
-\r
-}      cm_async_mad_t;\r
-\r
-/*\r
- * Structure to queue timer item to an asynch proc\r
- */\r
-typedef struct _cm_async_timer\r
-{\r
-       cl_async_proc_item_t    item;\r
-       al_conn_t                               *p_conn;\r
-\r
-}      cm_async_timer_t;\r
-\r
-\r
-/*\r
- * Global definitions to commonly used cm functions\r
- */\r
-al_conn_t*\r
-__get_conn(\r
-       IN              const   ib_al_handle_t                  h_al,\r
-       IN              const   ib_qp_type_t                    qp_type );\r
-\r
-void\r
-__ref_conn(\r
-       IN                              al_conn_t* const                        p_conn );\r
-\r
-void\r
-__deref_conn(\r
-       IN                              al_conn_t* const                        p_conn );\r
-\r
-void\r
-__release_req_info(\r
-       IN                              al_conn_t* const                        p_conn );\r
-\r
-void\r
-__process_cm_req(\r
-       IN                              cl_async_proc_item_t            *p_item );\r
-\r
-void\r
-__process_cm_mra(\r
-       IN                              cl_async_proc_item_t            *p_item );\r
-\r
-void\r
-__process_cm_rej(\r
-       IN                              cl_async_proc_item_t            *p_item );\r
-\r
-void\r
-__process_cm_rep(\r
-       IN                              cl_async_proc_item_t            *p_item );\r
-\r
-void\r
-__process_cm_rtu(\r
-       IN                              cl_async_proc_item_t            *p_item );\r
-\r
-void\r
-__process_cm_dreq(\r
-       IN                              cl_async_proc_item_t            *p_item );\r
-\r
-void\r
-__process_cm_drep(\r
-       IN                              cl_async_proc_item_t            *p_item );\r
-\r
-void\r
-__process_cm_lap(\r
-       IN                              cl_async_proc_item_t            *p_item );\r
-\r
-void\r
-__process_cm_apr(\r
-       IN                              cl_async_proc_item_t            *p_item );\r
-\r
-void\r
-__proc_conn_timeout(\r
-       IN                              cl_async_proc_item_t            *p_item );\r
-\r
-void\r
-__proc_lap_timeout(\r
-       IN                              cl_async_proc_item_t*           p_item );\r
-\r
-void\r
-__proc_dconn_timeout(\r
-       IN                              cl_async_proc_item_t*           p_item );\r
-\r
-void\r
-__validate_listens( void );\r
-\r
-ib_api_status_t\r
-__cm_send(\r
-       IN                              cm_port_agent_t* const          p_port_cm,\r
-       IN                              al_conn_t* const                        p_conn );\r
-\r
-ib_api_status_t\r
-__cm_send_mad(\r
-       IN                              cm_port_agent_t* const          p_port_cm,\r
-       IN                              ib_mad_element_t* const         p_mad );\r
-\r
-ib_api_status_t\r
-__cm_lap_qp(\r
-       IN                              al_conn_t* const                        p_conn );\r
-\r
-ib_api_status_t\r
-cm_conn_req(\r
-       IN              const   ib_al_handle_t                          h_al,\r
-       IN              const   ib_cm_req_t* const                      p_cm_req );\r
-\r
-ib_api_status_t\r
-cm_conn_lap(\r
-       IN              const   ib_cm_lap_t* const                      p_cm_lap );\r
-\r
-ib_api_status_t\r
-cm_conn_apr(\r
-       IN              const   ib_cm_handle_t                          h_cm_lap,\r
-       IN              const   ib_cm_apr_t* const                      p_cm_apr );\r
-\r
-ib_api_status_t\r
-cm_conn_dreq(\r
-       IN              const   ib_cm_dreq_t* const                     p_cm_dreq );\r
-\r
-ib_api_status_t\r
-cm_conn_drep(\r
-       IN              const   ib_cm_drep_t* const                     p_cm_drep,\r
-               OUT                     al_conn_t*              const           p_conn );\r
-\r
-void\r
-cm_async_event_cb(\r
-       IN              const   ib_async_event_rec_t* const     p_event_rec );\r
-\r
-//***TODO: The following two functions need to be called when the corresponding\r
-//***TODO: events occur on the QP.\r
-/*\r
- * Called when the HCA generates the communication established event.\r
- * This happens when a receive happens when in the RTR state, indicating\r
- * a dropped RTU.\r
- */\r
-void\r
-cm_conn_established(\r
-       IN                              al_conn_t* const                        p_conn );\r
-\r
-/*\r
- * Called when the HCA migrates to the alternate path.\r
- */\r
-void\r
-cm_conn_migrated(\r
-       IN                              al_conn_t* const                        p_conn );\r
-\r
-ib_api_status_t\r
-create_cm(\r
-       IN                              al_obj_t* const                         p_parent_obj );\r
-\r
-void\r
-__repeated_mad(\r
-       IN                              cm_port_agent_t* const          p_port_cm,\r
-       IN                              al_conn_t* const                        p_conn,\r
-       IN                              ib_mad_element_t* const         p_mad );\r
-\r
-void\r
-__conn_release(\r
-       IN                              al_conn_t* const                        p_conn );\r
-\r
-boolean_t\r
-__is_lid_valid(\r
-       IN                              ib_net16_t                                      lid,\r
-       IN                              ib_net16_t                                      port_lid,\r
-       IN                              uint8_t                                         lmc );\r
-\r
-ib_api_status_t\r
-cm_conn_rep(\r
-       IN                              al_conn_t*       const                  p_conn,\r
-       IN      const           ib_cm_rep_t* const                      p_cm_rep );\r
-\r
-ib_api_status_t\r
-cm_conn_rtu(\r
-       IN                              al_conn_t*       const                  p_conn,\r
-       IN              const   ib_cm_rtu_t* const                      p_cm_rtu );\r
-\r
-void\r
-__conn_reject(\r
-       IN                              al_conn_t* const                        p_conn,\r
-       IN              const   ib_rej_status_t                         reason,\r
-       IN              const   ib_ari_t* const                         p_ari OPTIONAL,\r
-       IN              const   uint8_t                                         ari_length,\r
-       IN              const   ib_rej_pdata_t* const           p_rej_pdata OPTIONAL );\r
-\r
-\r
-void\r
-__sidr_conn_to_passive(\r
-       IN                              ib_mad_element_t*       const   p_mad,\r
-       IN      OUT                     al_conn_t* const                        p_conn,\r
-       IN              const   mad_cm_sidr_req_t* const        p_req );\r
-\r
-ib_api_status_t\r
-cm_sidr_req(\r
-       IN              const   ib_al_handle_t                          h_al,\r
-       IN              const   ib_cm_req_t* const                      p_cm_req );\r
-\r
-ib_api_status_t\r
-cm_sidr_rep(\r
-       IN                              al_conn_t*       const                  p_conn,\r
-       IN              const   ib_cm_rep_t* const                      p_cm_rep );\r
-\r
-void\r
-__process_cm_sidr_req(\r
-       IN                              cl_async_proc_item_t            *p_item );\r
-\r
-void\r
-__process_cm_sidr_rep(\r
-       IN                              cl_async_proc_item_t            *p_item );\r
-\r
-ib_api_status_t\r
-__cm_pre_req(\r
-       IN      OUT                     al_conn_t*       const                  p_conn );\r
-\r
-ib_api_status_t\r
-__cm_pre_rep(\r
-       IN      OUT                     al_conn_t*       const                  p_conn,\r
-       IN      OUT     const   ib_cm_rep_t*                            p_cm_rep );\r
-\r
-ib_api_status_t\r
-__cm_pre_rtu(\r
-       IN      OUT                     al_conn_t*       const                  p_conn );\r
-\r
-void\r
-__bind_qp(\r
-       IN                              al_conn_t*                      const   p_conn,\r
-       IN              const   ib_qp_handle_t                          h_qp );\r
-\r
-void\r
-__cm_conn_unbind(\r
-       IN                              al_conn_t* const                        p_conn,\r
-       IN              const   uint32_t                                        timewait );\r
-\r
-ib_api_status_t\r
-cm_listen(\r
-       IN              const   ib_al_handle_t                          h_al,\r
-       IN              const   ib_cm_listen_t* const           p_cm_listen,\r
-       IN              const   ib_pfn_listen_err_cb_t          pfn_listen_err_cb,\r
-       IN              const   void* const                                     listen_context,\r
-               OUT                     ib_listen_handle_t* const       ph_cm_listen );\r
-\r
-ib_api_status_t\r
-cm_conn_rej(\r
-       IN                              al_conn_t*       const                  p_conn,\r
-       IN              const   ib_cm_rej_t* const                      p_cm_rej );\r
-\r
-ib_api_status_t\r
-cm_conn_mra(\r
-       IN                              al_conn_t*       const                  p_conn,\r
-       IN              const   ib_cm_mra_t* const                      p_cm_mra );\r
-\r
-ib_api_status_t\r
-cm_force_apm(\r
-       IN              const   ib_qp_handle_t                          h_qp );\r
-\r
-ib_api_status_t\r
-__conn_save_user_req(\r
-       IN              const   ib_cm_req_t* const                      p_cm_req,\r
-               OUT                     al_conn_t*       const                  p_conn,\r
-               OUT                     cm_port_agent_t** const         pp_port_cm );\r
-\r
-ib_api_status_t\r
-__format_mad_req(\r
-       IN              const   ib_cm_req_t* const                      p_cm_req,\r
-       IN      OUT                     al_conn_t* const                        p_conn );\r
-\r
-ib_rej_status_t\r
-__conn_save_user_rep(\r
-       IN              const   ib_cm_rep_t* const                      p_cm_rep,\r
-       IN      OUT                     al_conn_t*       const                  p_conn,\r
-               OUT                     cm_port_agent_t** const         pp_port_cm );\r
-\r
-ib_api_status_t\r
-__format_mad_rep(\r
-       IN              const   ib_cm_rep_t* const                      p_cm_rep,\r
-       IN      OUT                     al_conn_t* const                        p_conn );\r
-\r
-void\r
-__conn_abort(\r
-       IN                              al_conn_t* const                        p_conn );\r
-\r
-void\r
-__conn_timer_cb(\r
-       IN                              void                                            *context );\r
-\r
-ib_api_status_t\r
-__get_port_attr(\r
-       IN              const   ib_gid_t* const                         p_gid,\r
-       IN              const   ib_net16_t                                      lid,\r
-               OUT                     cm_port_agent_t** const         pp_port_cm OPTIONAL,\r
-               OUT                     ib_ca_attr_t** const            pp_ca_attr OPTIONAL );\r
-\r
-ib_api_status_t\r
-__conn_save_user_rtu(\r
-       IN              const   ib_cm_rtu_t* const                      p_cm_rtu,\r
-       IN      OUT                     al_conn_t*       const                  p_conn,\r
-               OUT                     cm_port_agent_t** const         pp_port_cm );\r
-\r
-ib_api_status_t\r
-__validate_lap_path(\r
-       IN                              al_conn_t* const                        p_conn,\r
-               OUT                     cm_port_agent_t** const         pp_port_cm,\r
-               OUT                     uint8_t* const                          p_ack_delay );\r
-\r
-ib_api_status_t\r
-cm_conn_handoff(\r
-       IN                              al_conn_t*       const                  p_conn,\r
-       IN              const   net64_t                                         svc_id );\r
-\r
-void\r
-__init_av(\r
-       IN              const   ib_port_attr_t* const           p_port_attr,\r
-       IN              const   ib_path_rec_t* const            p_path,\r
-       IN              const   al_conn_t*       const                  p_conn,\r
-               OUT                     ib_av_attr_t* const                     p_av );\r
-\r
-void\r
-__format_mad_rtu(\r
-       IN              const   ib_cm_rtu_t* const                      p_cm_rtu,\r
-       IN      OUT                     al_conn_t* const                        p_conn );\r
-\r
-ib_api_status_t\r
-__format_mad_lap_path(\r
-       IN              const   ib_path_rec_t* const            p_path_rec,\r
-       IN              const   uint8_t                                         ack_delay,\r
-               OUT                     lap_path_info_t* const          p_lap_path );\r
-\r
-void\r
-__format_mad_dreq(\r
-       IN              const   ib_cm_dreq_t* const                     p_cm_dreq,\r
-               OUT                     al_conn_t*              const           p_conn );\r
-\r
-void\r
-__format_mad_drep(\r
-       IN              const   ib_cm_drep_t*   const           p_cm_drep,\r
-               OUT                     al_conn_t*              const           p_conn );\r
-\r
-ib_api_status_t\r
-__validate_primary_path(\r
-       IN      OUT                     al_conn_t* const                        p_conn,\r
-               OUT                     cm_port_agent_t** const         pp_port_cm );\r
-\r
-ib_api_status_t\r
-__validate_alt_path(\r
-       IN      OUT                     al_conn_t* const                        p_conn );\r
-\r
-\r
-#endif /* __IB_AL_CM_H__ */\r
diff --git a/core/al/al_cm_shared.c b/core/al/al_cm_shared.c
deleted file mode 100644 (file)
index 7da15fe..0000000
+++ /dev/null
@@ -1,470 +0,0 @@
-/*\r
- * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
- * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. \r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- *     Redistribution and use in source and binary forms, with or\r
- *     without modification, are permitted provided that the following\r
- *     conditions are met:\r
- *\r
- *      - Redistributions of source code must retain the above\r
- *        copyright notice, this list of conditions and the following\r
- *        disclaimer.\r
- *\r
- *      - Redistributions in binary form must reproduce the above\r
- *        copyright notice, this list of conditions and the following\r
- *        disclaimer in the documentation and/or other materials\r
- *        provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- * $Id$\r
- */\r
-\r
-#include "al_ci_ca.h"\r
-#include "al_cm_shared.h"\r
-#include "al_debug.h"\r
-#include "al_qp.h"\r
-\r
-\r
-\r
-static ib_api_status_t\r
-__reset_qp(\r
-       IN              const   ib_qp_handle_t                          h_qp )\r
-{\r
-       ib_qp_mod_t                     qp_mod;\r
-       ib_api_status_t         status;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       cl_memclr( &qp_mod, sizeof(ib_qp_mod_t) );\r
-       qp_mod.req_state = IB_QPS_RESET;\r
-\r
-       status = ib_modify_qp( h_qp, &qp_mod );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("ib_modify_qp to IB_QPS_RESET returned %s\n",\r
-                       ib_get_err_str(status) ) );\r
-       }\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return status;\r
-}\r
-\r
-\r
-\r
-static ib_api_status_t\r
-__init_qp(\r
-       IN              const   ib_qp_handle_t                          h_qp,\r
-       IN                              ib_gid_t * const                        p_gid,\r
-       IN              const   uint16_t                                        pkey,\r
-       IN              const   ib_access_t                                     access_ctrl )\r
-{\r
-       ib_port_attr_t          *p_port_attr;\r
-       ib_qp_mod_t                     qp_mod;\r
-       ib_api_status_t         status;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       cl_memclr( &qp_mod, sizeof(ib_qp_mod_t) );\r
-       qp_mod.req_state = IB_QPS_INIT;\r
-       qp_mod.state.init.access_ctrl = access_ctrl;\r
-\r
-       /* Get the port and PKEY information. */\r
-       ci_ca_lock_attr( h_qp->obj.p_ci_ca );\r
-       p_port_attr = get_port_attr( h_qp->obj.p_ci_ca->p_pnp_attr, p_gid );\r
-       if( !p_port_attr )\r
-       {\r
-               ci_ca_unlock_attr( h_qp->obj.p_ci_ca );\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("invalid p_gid\n" ) );\r
-               return IB_INVALID_GID;\r
-       }\r
-\r
-       qp_mod.state.init.primary_port = p_port_attr->port_num;\r
-       qp_mod.state.init.pkey_index = get_pkey_index( p_port_attr, pkey );\r
-       ci_ca_unlock_attr( h_qp->obj.p_ci_ca );\r
-\r
-       if( qp_mod.state.init.pkey_index == BAD_PKEY_INDEX )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("invalid PKEY\n" ) );\r
-               return IB_INVALID_PKEY;\r
-       }\r
-\r
-       status = ib_modify_qp( h_qp, &qp_mod );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("ib_modify_qp to IB_QPS_INIT returned %s\n",\r
-                       ib_get_err_str(status) ) );\r
-       }\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return status;\r
-}\r
-\r
-\r
-\r
-/*\r
- * Transition the QP to the INIT state, if it is not already in the\r
- * INIT state.\r
- */\r
-ib_api_status_t\r
-cm_init_qp(\r
-       IN              const   ib_qp_handle_t                          h_qp,\r
-       IN                              ib_gid_t * const                        p_gid,\r
-       IN              const   uint16_t                                        pkey,\r
-       IN              const   ib_access_t                                     access_ctrl )\r
-{\r
-       ib_api_status_t                 status;\r
-\r
-       /*\r
-        * Move to the init state to allow posting of receive buffers.\r
-        * Chech the current state of the QP.  The user may have already\r
-        * transitioned it and posted some receives to the QP, so we\r
-        * should not reset the QP if it is already in the INIT state.\r
-        */\r
-       if( h_qp->state != IB_QPS_INIT )\r
-       {\r
-               /* Reset the QP. */\r
-               status = __reset_qp( h_qp );\r
-               if( status != IB_SUCCESS )\r
-               {\r
-                       AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                               ("__reset_qp returned %s\n", ib_get_err_str(status) ) );\r
-                       return status;\r
-               }\r
-\r
-               /* Initialize the QP. */\r
-               status = __init_qp( h_qp, p_gid, pkey, access_ctrl );\r
-               if( status != IB_SUCCESS )\r
-               {\r
-                       AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                               ("__init_qp returned %s.\n", ib_get_err_str(status) ) );\r
-                       return status;\r
-               }\r
-       }\r
-\r
-       return IB_SUCCESS;\r
-}\r
-\r
-\r
-\r
-ib_api_status_t\r
-cm_rts_qp(\r
-       IN              const   ib_qp_handle_t                          h_qp,\r
-       IN                              ib_qp_mod_t     * const                 p_qp_mod_rtr,\r
-       IN                              ib_qp_mod_t * const                     p_qp_mod_rts )\r
-{\r
-       ib_api_status_t status;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       /* Set the QP to RTR. */\r
-       status = ib_modify_qp( h_qp, p_qp_mod_rtr );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("ib_modify_qp to RTR returned %s.\n", ib_get_err_str(status) ) );\r
-               return status;\r
-       }\r
-\r
-       /* Set the QP to RTS. */\r
-       status = ib_modify_qp( h_qp, p_qp_mod_rts );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("ib_modify_qp to RTS returned %s.\n", ib_get_err_str(status) ) );\r
-               return status;\r
-       }\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return IB_SUCCESS;\r
-}\r
-\r
-\r
-\r
-/*\r
- * Transition the QP to the error state to flush all oustanding work\r
- * requests, then transition it back into the reset state.  This function\r
- * may be called when destroying the QP in order to flush all work requests,\r
- * so we cannot call through the main API, or the call will fail since the\r
- * QP is no longer in the initialize state.\r
- */\r
-ib_api_status_t\r
-cm_reset_qp(\r
-       IN              const   ib_qp_handle_t                          h_qp,\r
-       IN              const   uint32_t                                        timewait )\r
-{\r
-       ib_qp_mod_t                     qp_mod;\r
-       ib_api_status_t         status;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       /* Special checks on the QP state for error handling - see above. */\r
-       if( !h_qp || !AL_OBJ_IS_TYPE( h_qp, AL_OBJ_TYPE_H_QP ) ||\r
-               ( (h_qp->obj.state != CL_INITIALIZED) && \r
-                 (h_qp->obj.state != CL_DESTROYING) ) )\r
-       {\r
-               AL_PRINT_EXIT( TRACE_LEVEL_WARNING, AL_DBG_CM, ("IB_INVALID_QP_HANDLE\n") );\r
-               return IB_INVALID_QP_HANDLE;\r
-       }\r
-\r
-       /*\r
-        * Only modify the QP if it is not exported to UM.  All UM QP modifications\r
-        * are initiated in UM.\r
-        */\r
-       if( !AL_OBJ_IS_SUBTYPE( h_qp, AL_OBJ_SUBTYPE_UM_EXPORT ) )\r
-       {\r
-               cl_memclr( &qp_mod, sizeof(ib_qp_mod_t) );\r
-               qp_mod.req_state = IB_QPS_ERROR;\r
-\r
-               /* Modify to error state using function pointers - see above. */\r
-               status = h_qp->pfn_modify_qp( h_qp, &qp_mod, NULL );\r
-               if( status != IB_SUCCESS )\r
-               {\r
-                       AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                               ("pfn_modify_qp to IB_QPS_ERROR returned %s\n",\r
-                               ib_get_err_str(status) ) );\r
-                       return status;\r
-               }\r
-       }\r
-\r
-#ifdef CL_KERNEL\r
-       /* Store the timestamp after which the QP exits timewait. */\r
-       h_qp->timewait = cl_get_time_stamp() + (((uint64_t)timewait) * 1000);\r
-#else\r
-       UNUSED_PARAM( timewait );\r
-#endif /* CL_KERNEL */\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return IB_SUCCESS;\r
-}\r
-\r
-\r
-\r
-/*\r
- * Save the information from a user's CM reply needed to transition the QP\r
- * to the RTR and RTS states.\r
- */\r
-void\r
-cm_save_rep_qp_attr(\r
-       IN              const   ib_cm_rep_t * const                     p_cm_rep,\r
-       IN              const   ib_port_attr_t * const          p_port_attr,\r
-       IN              const   ib_path_rec_t * const           p_path_rec,\r
-       IN              const   ib_path_rec_t * const           p_alt_path_rec,\r
-       IN OUT                  ib_qp_mod_t * const                     p_qp_mod_rtr,\r
-       IN OUT                  ib_qp_mod_t * const                     p_qp_mod_rts )\r
-{\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       /* Update the QP RTR transition information. */\r
-       p_qp_mod_rtr->state.rtr.rq_psn = p_cm_rep->h_qp->num;\r
-\r
-       if( p_cm_rep->access_ctrl )\r
-       {\r
-               p_qp_mod_rtr->state.rtr.opts |= IB_MOD_QP_ACCESS_CTRL;\r
-               p_qp_mod_rtr->state.rtr.access_ctrl = p_cm_rep->access_ctrl;\r
-       }\r
-\r
-       if( p_cm_rep->sq_depth )\r
-       {\r
-               p_qp_mod_rtr->state.rtr.opts |= IB_MOD_QP_SQ_DEPTH;\r
-               p_qp_mod_rtr->state.rtr.sq_depth = p_cm_rep->sq_depth;\r
-       }\r
-\r
-       if( p_cm_rep->rq_depth )\r
-       {\r
-               p_qp_mod_rtr->state.rtr.opts |= IB_MOD_QP_RQ_DEPTH;\r
-               p_qp_mod_rtr->state.rtr.rq_depth = p_cm_rep->rq_depth;\r
-       }\r
-\r
-       if( p_cm_rep->rnr_nak_timeout )\r
-       {\r
-               p_qp_mod_rtr->state.rtr.opts |= IB_MOD_QP_RNR_NAK_TIMEOUT;\r
-               p_qp_mod_rtr->state.rtr.rnr_nak_timeout = p_cm_rep->rnr_nak_timeout;\r
-       }\r
-\r
-       /* Some common checks for QP RTR and RTS transition information. */\r
-       if( p_cm_rep->h_qp && p_cm_rep->h_qp->type == IB_QPT_RELIABLE_CONN )\r
-       {\r
-               p_qp_mod_rts->state.rts.init_depth = p_cm_rep->init_depth;\r
-       }\r
-\r
-       /* Update the QP RTS transition information starting here. */\r
-       p_qp_mod_rts->state.rts.retry_cnt = p_cm_rep->rnr_retry_cnt;\r
-       p_qp_mod_rts->state.rts.rnr_retry_cnt = p_cm_rep->rnr_retry_cnt;\r
-       p_qp_mod_rts->state.rts.rnr_nak_timeout = p_cm_rep->rnr_nak_timeout;\r
-\r
-       if( p_cm_rep->failover_accepted == IB_FAILOVER_ACCEPT_SUCCESS )\r
-       {\r
-               p_qp_mod_rts->state.rts.opts |= IB_MOD_QP_APM_STATE;\r
-               p_qp_mod_rts->state.rts.apm_state = IB_APM_REARM;\r
-       }\r
-\r
-       /* Setup the primary address vector. */\r
-       p_qp_mod_rtr->state.rtr.opts |= IB_MOD_QP_PRIMARY_AV;\r
-       cm_save_path_av( p_port_attr, p_path_rec, p_cm_rep->rnr_retry_cnt,\r
-               p_cm_rep->rnr_retry_cnt, &p_qp_mod_rtr->state.rtr.primary_av );\r
-\r
-       /* Setup alternate address vector. */\r
-       if( p_alt_path_rec->slid )\r
-       {\r
-               p_qp_mod_rtr->state.rtr.opts |= IB_MOD_QP_ALTERNATE_AV;\r
-               cm_save_path_av( p_port_attr, p_alt_path_rec, p_cm_rep->rnr_retry_cnt,\r
-                       p_cm_rep->rnr_retry_cnt, &p_qp_mod_rtr->state.rtr.alternate_av );\r
-       }\r
-\r
-       p_qp_mod_rts->state.rts.local_ack_timeout =\r
-               cm_local_ack_timeout( ib_path_rec_pkt_life( p_path_rec ),\r
-               p_cm_rep->target_ack_delay );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-\r
-/*\r
- * Save the information from a user's CM RTU needed to transition the QP\r
- * to the RTR and RTS states.\r
- */\r
-void\r
-cm_save_rtu_qp_attr(\r
-       IN              const   ib_cm_rtu_t * const                     p_cm_rtu,\r
-       IN OUT                  ib_qp_mod_t * const                     p_qp_mod_rtr )\r
-{\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       /* Update the QP RTR transition information. */\r
-       if( p_cm_rtu->access_ctrl )\r
-       {\r
-               p_qp_mod_rtr->state.rtr.opts |= IB_MOD_QP_ACCESS_CTRL;\r
-               p_qp_mod_rtr->state.rtr.access_ctrl = p_cm_rtu->access_ctrl;\r
-       }\r
-\r
-       if( p_cm_rtu->sq_depth )\r
-       {\r
-               p_qp_mod_rtr->state.rtr.opts |= IB_MOD_QP_SQ_DEPTH;\r
-               p_qp_mod_rtr->state.rtr.sq_depth = p_cm_rtu->sq_depth;\r
-       }\r
-\r
-       if( p_cm_rtu->rq_depth )\r
-       {\r
-               p_qp_mod_rtr->state.rtr.opts |= IB_MOD_QP_RQ_DEPTH;\r
-               p_qp_mod_rtr->state.rtr.rq_depth = p_cm_rtu->rq_depth;\r
-       }\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-\r
-/*\r
- * Save the information about a path record needed to specify an\r
- * address vector for a connected QP.\r
- */\r
-void\r
-cm_save_path_av(\r
-       IN              const   ib_port_attr_t * const          p_port_attr,\r
-       IN              const   ib_path_rec_t * const           p_path_rec,\r
-       IN              const   uint8_t                                         retry_cnt,\r
-       IN              const   uint8_t                                         rnr_retry_cnt,\r
-               OUT                     ib_av_attr_t * const            p_av )\r
-{\r
-       p_av->port_num = p_port_attr->port_num;\r
-       p_av->sl = ib_path_rec_sl( p_path_rec );\r
-       p_av->dlid = p_path_rec->dlid;\r
-\r
-       if( p_path_rec->hop_flow_raw.val )\r
-       {\r
-               p_av->grh_valid = TRUE;\r
-               p_av->grh.ver_class_flow = ib_grh_set_ver_class_flow( 1,\r
-                       p_path_rec->tclass, ib_path_rec_flow_lbl( p_path_rec ) );\r
-               p_av->grh.resv1 = 0;\r
-               p_av->grh.resv2 = 0;\r
-               p_av->grh.hop_limit = ib_path_rec_hop_limit( p_path_rec );\r
-               p_av->grh.src_gid = p_path_rec->sgid;\r
-               p_av->grh.dest_gid = p_path_rec->dgid;\r
-       }\r
-       else\r
-       {\r
-               p_av->grh_valid = FALSE;\r
-       }\r
-\r
-       p_av->static_rate = ib_path_rec_rate( p_path_rec );\r
-       p_av->path_bits = (uint8_t)(p_path_rec->slid - p_port_attr->lid);\r
-       p_av->conn.path_mtu = ib_path_rec_mtu( p_path_rec );\r
-       p_av->conn.local_ack_timeout = cm_local_ack_timeout(\r
-               ib_path_rec_pkt_life( p_path_rec ), 0 );\r
-\r
-       p_av->conn.seq_err_retry_cnt = retry_cnt;\r
-       p_av->conn.rnr_retry_cnt = rnr_retry_cnt;\r
-\r
-}\r
-\r
-\r
-\r
-/*\r
- * Return the local ACK timeout value based on the given packet lifetime\r
- * and target ACK delay.  Both input values are assumed to be in the form\r
- * 4.096 x 2 ^ input.\r
- */\r
-uint8_t\r
-cm_local_ack_timeout(\r
-       IN              const   uint8_t                                         pkt_lifetime,\r
-       IN              const   uint8_t                                         target_ack_delay )\r
-{\r
-       uint64_t        timeout;\r
-       uint8_t         local_ack_timeout;\r
-\r
-       /*\r
-        * Since both input and the output values are in the same form, we\r
-        * can ignore the 4.096 portion by dividing it out.\r
-        */\r
-\r
-       /* Double the packet lifetime to get the round trip time. */\r
-       timeout = (uint64_t)2 << pkt_lifetime;\r
-\r
-       /* Add in the target ack delay. */\r
-       if( target_ack_delay )\r
-               timeout += (uint64_t)1 << target_ack_delay;\r
-\r
-       /* Calculate the local ACK timeout. */\r
-       local_ack_timeout = 1;\r
-       while( (1 << local_ack_timeout) <= timeout )\r
-       {\r
-               local_ack_timeout++;\r
-\r
-               /* Only 5-bits are valid. */\r
-               if( local_ack_timeout > MAX_LOCAL_ACK_TIMEOUT )\r
-                       return MAX_LOCAL_ACK_TIMEOUT;\r
-       }\r
-\r
-       return local_ack_timeout;\r
-}\r
-\r
-\r
-/*\r
- * Remove the link between the connection object and QP, but continue\r
- * holding any references\r
- */\r
-void\r
-cm_unbind_qp(\r
-       IN              const   ib_cm_handle_t                  h_conn )\r
-{\r
-       /* If the connection isn't bound to a QP, just return. */\r
-       if( h_conn->h_qp )\r
-       {\r
-               ((al_conn_qp_t*)h_conn->h_qp)->p_conn = NULL;\r
-               h_conn->h_qp = NULL;\r
-       }\r
-}\r
diff --git a/core/al/al_cm_shared.h b/core/al/al_cm_shared.h
deleted file mode 100644 (file)
index a745776..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*\r
- * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
- * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. \r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- *     Redistribution and use in source and binary forms, with or\r
- *     without modification, are permitted provided that the following\r
- *     conditions are met:\r
- *\r
- *      - Redistributions of source code must retain the above\r
- *        copyright notice, this list of conditions and the following\r
- *        disclaimer.\r
- *\r
- *      - Redistributions in binary form must reproduce the above\r
- *        copyright notice, this list of conditions and the following\r
- *        disclaimer in the documentation and/or other materials\r
- *        provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- * $Id$\r
- */\r
-\r
-#if !defined(__IB_AL_CM_SHARED_H__)\r
-#define __IB_AL_CM_SHARED_H__\r
-\r
-#include <iba/ib_al.h>\r
-#include "al_qp.h"\r
-\r
-#if defined(CL_KERNEL)\r
-#include "al_cm.h"\r
-#else\r
-#include "ual_cm.h"\r
-#endif\r
-\r
-\r
-\r
-ib_api_status_t\r
-cm_reset_qp(\r
-       IN              const   ib_qp_handle_t                          h_qp,\r
-       IN              const   uint32_t                                        timewait );\r
-\r
-ib_api_status_t\r
-cm_init_qp(\r
-       IN              const   ib_qp_handle_t                          h_qp,\r
-       IN                              ib_gid_t * const                        p_gid,\r
-       IN              const   uint16_t                                        pkey,\r
-       IN              const   ib_access_t                                     access_ctrl );\r
-\r
-ib_api_status_t\r
-cm_rts_qp(\r
-       IN              const   ib_qp_handle_t                          h_qp,\r
-       IN                              ib_qp_mod_t     * const                 p_qp_mod_rtr,\r
-       IN                              ib_qp_mod_t * const                     p_qp_mod_rts );\r
-\r
-void\r
-cm_save_rep_qp_attr(\r
-       IN              const   ib_cm_rep_t * const                     p_cm_rep,\r
-       IN              const   ib_port_attr_t * const          p_port_attr,\r
-       IN              const   ib_path_rec_t * const           p_path_rec,\r
-       IN              const   ib_path_rec_t * const           p_alt_path_rec,\r
-       IN OUT                  ib_qp_mod_t * const                     p_qp_mod_rtr,\r
-       IN OUT                  ib_qp_mod_t * const                     p_qp_mod_rts );\r
-\r
-void\r
-cm_save_rtu_qp_attr(\r
-       IN              const   ib_cm_rtu_t * const                     p_cm_rtu,\r
-       IN      OUT                     ib_qp_mod_t     * const                 p_qp_mod_rtr );\r
-\r
-void\r
-cm_save_path_av(\r
-       IN              const   ib_port_attr_t * const          p_port_attr,\r
-       IN              const   ib_path_rec_t * const           p_path_rec,\r
-       IN              const   uint8_t                                         retry_cnt,\r
-       IN              const   uint8_t                                         rnr_retry_cnt,\r
-               OUT                     ib_av_attr_t * const            p_av );\r
-\r
-\r
-#define MAX_LOCAL_ACK_TIMEOUT          0x1F            /* limited to 5 bits */\r
-uint8_t\r
-cm_local_ack_timeout(\r
-       IN              const   uint8_t                                         pkt_lifetime,\r
-       IN              const   uint8_t                                         target_ack_delay );\r
-\r
-/* Called by the QP upon destruction if still connected. */\r
-void\r
-cm_conn_destroy(\r
-       IN                              al_conn_qp_t * const            p_conn_qp );\r
-\r
-/*\r
- * Called by AL to destroy connection objects that were not destroyed\r
- * properly.\r
- */\r
-void\r
-cm_cleanup_conn(\r
-       IN              const   ib_cm_handle_t                          h_conn );\r
-\r
-\r
-/*\r
- * Remove the link between the connection object and QP, but continue\r
- * holding any references\r
- */\r
-void\r
-cm_unbind_qp(\r
-       IN              const   ib_cm_handle_t                  h_conn );\r
-\r
-\r
-#endif /* __IB_AL_CM_SHARED_H__ */\r
diff --git a/core/al/kernel/al_cm.c b/core/al/kernel/al_cm.c
deleted file mode 100644 (file)
index 45c83e9..0000000
+++ /dev/null
@@ -1,1910 +0,0 @@
-/*\r
- * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
- * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. \r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- *     Redistribution and use in source and binary forms, with or\r
- *     without modification, are permitted provided that the following\r
- *     conditions are met:\r
- *\r
- *      - Redistributions of source code must retain the above\r
- *        copyright notice, this list of conditions and the following\r
- *        disclaimer.\r
- *\r
- *      - Redistributions in binary form must reproduce the above\r
- *        copyright notice, this list of conditions and the following\r
- *        disclaimer in the documentation and/or other materials\r
- *        provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- * $Id$\r
- */\r
-\r
-#include <iba/ib_al.h>\r
-\r
-#include "al.h"\r
-#include "al_av.h"\r
-#include "al_ca.h"\r
-#include "al_cm.h"\r
-#include "al_cm_shared.h"\r
-#include "al_debug.h"\r
-\r
-#if defined(EVENT_TRACING)\r
-#ifdef offsetof\r
-#undef offsetof\r
-#endif\r
-#include "al_cm.tmh"\r
-#endif\r
-\r
-#include "al_mgr.h"\r
-#include "al_qp.h"\r
-\r
-#include "ib_common.h"\r
-\r
-\r
-\r
-\r
-/*\r
- * Comm id\r
- * Note: Running Comm id is a global number in this implementation.\r
- */\r
-atomic32_t             local_comm_id = 1;\r
-\r
-/* NOTES:\r
- * The global cm object has a lock, as do connection objects.  It is OK\r
- * to acquire the global cm object's lock when already holding a connection\r
- * object's lock.  This means that it is not possible to acquire a connection's\r
- * lock after acquiring the global cm's lock.  Connection objects provide\r
- * reference counting to allow releasing the global cm's lock and acquiring\r
- * the connection's lock.\r
- *\r
- * Callbacks where users are expected to call a CM function hold a reference\r
- * on the connection object until the expected call is made.  These include:\r
- *     REQ callback - expect REP or REJ\r
- *     REP callback - expect RTU or REJ\r
- *     LAP callback - expect APR\r
- *     DREQ callback - expect DREP\r
- * The following callbacks do not expect a user call.\r
- *     RTU callback - connection is established.\r
- *     DREP callback - connection is released.\r
- *     APR callback - LAP transaction is complete.\r
- *     MRA callback - notification only.\r
- *\r
- * Connections are stored in the connection map once established using a 64-bit\r
- * key that is generated as (local_comm_id << 32 | remote_comm_id) if using the\r
- * connection as data source, or (remote_comm_id <<32 | local_comm_id) if using\r
- * a received MAD as source.\r
- *\r
- */\r
-\r
-\r
-/* Global instance of the CM agent. */\r
-al_cm_agent_t  *gp_cm = NULL;\r
-\r
-\r
-\r
-static void\r
-__parse_cm_info(void);\r
-\r
-\r
-static void\r
-__process_cm_send_comp(\r
-       IN                              cl_async_proc_item_t            *p_item );\r
-\r
-\r
-/* debug functions */\r
-static void\r
-__parse_cm_info()\r
-{\r
-#if defined( _DEBUG_ )\r
-       cl_list_item_t  *p_item;\r
-       al_listen_t             *p_listen;\r
-       al_conn_t               *p_conn;\r
-       uint32_t                i;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       cl_spinlock_acquire( &gp_cm->obj.lock );\r
-       AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_CM,\r
-               ("CM info:\n"\r
-               "\tactive_listen_list..: %"PRIdSIZE_T"\n"\r
-               "\tinactive_listen_list: %"PRIdSIZE_T"\n"\r
-               "\tpending_list........: %"PRIdSIZE_T"\n"\r
-               "\ttime_wait_list......: %"PRIdSIZE_T"\n"\r
-               "\tconn_pool...........: %"PRIdSIZE_T"\n"\r
-               "\treq_pool............: %"PRIdSIZE_T"\n"\r
-               "\tconn_map............: %"PRIdSIZE_T"\n",\r
-               cl_qlist_count( &gp_cm->active_listen_list ),\r
-               cl_qlist_count( &gp_cm->inactive_listen_list ),\r
-               cl_qlist_count( &gp_cm->pending_list ),\r
-               cl_qlist_count( &gp_cm->time_wait_list ),\r
-               cl_qpool_count( &gp_cm->conn_pool ),\r
-               cl_pool_count( &gp_cm->req_pool ),\r
-               cl_qmap_count( &gp_cm->conn_map ) ) );\r
-       /* walk lists for connection info */\r
-       AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_CM, ("Active listens:\n") );\r
-       i = 1;\r
-\r
-       for( p_item = cl_qlist_head( &gp_cm->active_listen_list );\r
-               p_item != cl_qlist_end( &gp_cm->active_listen_list );\r
-               p_item = cl_qlist_next( p_item ) )\r
-       {\r
-               p_listen = PARENT_STRUCT( p_item, al_listen_t, list_item );\r
-\r
-               AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_CM,\r
-                       ("\n%d)\n"\r
-                        "\tservice_id...:0x%I64x\n"\r
-                        "\tlid..........:0x%x\n"\r
-                        "\tport_guid....:0x%I64x\n"\r
-                        "\tqp_type......:%d\n",\r
-                        i++,\r
-                        p_listen->info.svc_id, p_listen->info.lid,\r
-                        p_listen->info.port_guid, p_listen->info.qp_type ) );\r
-       }\r
-\r
-\r
-       AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_CM, ("Inactive listens:\n") );\r
-       i = 1;\r
-\r
-       for( p_item = cl_qlist_head( &gp_cm->inactive_listen_list );\r
-               p_item != cl_qlist_end( &gp_cm->inactive_listen_list );\r
-               p_item = cl_qlist_next( p_item ) )\r
-       {\r
-               p_listen = PARENT_STRUCT( p_item, al_listen_t, list_item );\r
-\r
-               AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_CM,\r
-                       ("\n%d)\n"\r
-                        "\tservice_id...:0x%I64x\n"\r
-                        "\tlid..........:0x%x\n"\r
-                        "\tport_guid....:0x%I64x\n"\r
-                        "\tqp_type......:%d\n",\r
-                        i++,\r
-                        p_listen->info.svc_id, p_listen->info.lid,\r
-                        p_listen->info.port_guid, p_listen->info.qp_type ) );\r
-       }\r
-\r
-\r
-       AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_CM, ("In Timewait:\n") );\r
-       i = 1;\r
-\r
-       for( p_item = cl_qlist_head( &gp_cm->time_wait_list );\r
-               p_item != cl_qlist_end( &gp_cm->time_wait_list );\r
-               p_item = cl_qlist_next( p_item ) )\r
-       {\r
-               p_conn = PARENT_STRUCT( p_item, al_conn_t, map_item );\r
-\r
-               AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_CM,\r
-                       ("\n%d)\n"\r
-                        "\tstate........:%d\n"\r
-                        "\tref_cnt......:%d\n"\r
-                        "\tlocal_id.....:0x%x\n"\r
-                        "\tremote_id....:0x%x\n"\r
-                        "\tlocal_qpn....:0x%x\n"\r
-                        "\tremote_qpn...:0x%x\n",\r
-                        i++,\r
-                        p_conn->state, p_conn->ref_cnt, p_conn->local_comm_id,\r
-                        p_conn->remote_comm_id,\r
-                        cl_ntoh32(p_conn->local_qpn),\r
-                        cl_ntoh32(p_conn->remote_qpn) ) );\r
-       }\r
-\r
-       cl_spinlock_release( &gp_cm->obj.lock );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-#endif\r
-}\r
-\r
-\r
-/*\r
- * PnP callback invoked when deregistration is complete.\r
- */\r
-/***static***/ void\r
-__cm_pnp_dereg_cb(\r
-       IN                              void                                            *context )\r
-{\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       UNUSED_PARAM( context );\r
-\r
-       deref_al_obj( &gp_cm->obj );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-/*\r
- * Starts immediate cleanup of the CM.  Invoked during al_obj destruction.\r
- */\r
-/***static***/ void\r
-__destroying_cm(\r
-       IN                              al_obj_t*                                       p_obj )\r
-{\r
-       ib_api_status_t         status;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       CL_ASSERT( &gp_cm->obj == p_obj );\r
-       UNUSED_PARAM( p_obj );\r
-\r
-       /* Deregister from PnP notifications. */\r
-       if( gp_cm->h_pnp )\r
-       {\r
-               status = ib_dereg_pnp( gp_cm->h_pnp, __cm_pnp_dereg_cb );\r
-               if( status != IB_SUCCESS )\r
-               {\r
-                       AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                               ("ib_dereg_pnp failed with status %s.\n",\r
-                               ib_get_err_str(status)) );\r
-                       deref_al_obj( &gp_cm->obj );\r
-               }\r
-       }\r
-\r
-       /* Cancel all timewait timers. */\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-/*\r
- * Frees the global CM agent.  Invoked during al_obj destruction.\r
- */\r
-void\r
-__free_cm(\r
-       IN                              al_obj_t*                                       p_obj )\r
-{\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       CL_ASSERT( &gp_cm->obj == p_obj );\r
-       /* All listen request should have been cleaned up by this point. */\r
-       CL_ASSERT( cl_is_qlist_empty( &gp_cm->active_listen_list ) );\r
-       CL_ASSERT( cl_is_qlist_empty( &gp_cm->inactive_listen_list ) );\r
-       /* All connections should have been cancelled/disconnected by now. */\r
-       CL_ASSERT( cl_is_qlist_empty( &gp_cm->pending_list ) );\r
-       CL_ASSERT( cl_is_qmap_empty( &gp_cm->conn_map ) );\r
-\r
-       __parse_cm_info();\r
-\r
-       //***TODO: Figure out the right handling of the time wait state.\r
-       //***TODO: Must cancel all timewait timers.\r
-       /* Return all connection objects in the time-wait state to their pool. */\r
-       cl_qpool_put_list( &gp_cm->conn_pool, &gp_cm->time_wait_list );\r
-\r
-       /*\r
-        * All CM port agents should have been destroyed by now via the\r
-        * standard child object destruction provided by the al_obj.\r
-        */\r
-       cl_qpool_destroy( &gp_cm->conn_pool );\r
-       cl_pool_destroy( &gp_cm->req_pool );\r
-       destroy_al_obj( p_obj );\r
-\r
-       cl_free( gp_cm );\r
-       gp_cm = NULL;\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-/*\r
- * Performs immediate cleanup of resources.\r
- */\r
-/***static***/ void\r
-__destroying_port_cm(\r
-       IN                              al_obj_t                                        *p_obj )\r
-{\r
-       cm_port_agent_t         *p_port_cm;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_port_cm = PARENT_STRUCT( p_obj, cm_port_agent_t, obj );\r
-\r
-       if( p_port_cm->h_qp )\r
-       {\r
-               ib_destroy_qp( p_port_cm->h_qp, (ib_pfn_destroy_cb_t)deref_al_obj );\r
-               p_port_cm->h_qp = NULL;\r
-       }\r
-\r
-       if( p_port_cm->h_pd )\r
-       {\r
-               ib_dealloc_pd( p_port_cm->h_pd, (ib_pfn_destroy_cb_t)deref_al_obj );\r
-               p_port_cm->h_pd = NULL;\r
-       }\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-\r
-/*\r
- * Release all resources allocated by a port CM agent.  Finishes any cleanup\r
- * for a port agent.\r
- */\r
-/***static***/ void\r
-__free_port_cm(\r
-       IN                              al_obj_t                                        *p_obj )\r
-{\r
-       cm_port_agent_t         *p_port_cm;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_port_cm = PARENT_STRUCT( p_obj, cm_port_agent_t, obj );\r
-\r
-       CL_ASSERT( cl_is_qlist_empty( &p_port_cm->av_list ) );\r
-\r
-       if( p_port_cm->h_ca )\r
-               deref_al_obj( &p_port_cm->h_ca->obj );\r
-\r
-       cl_spinlock_destroy( &p_port_cm->lock );\r
-       destroy_al_obj( &p_port_cm->obj );\r
-       cl_free( p_port_cm );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-ib_api_status_t\r
-__get_av(\r
-       IN                              cm_port_agent_t* const          p_port_cm,\r
-       IN                              ib_mad_element_t                        *p_mad )\r
-{\r
-       ib_api_status_t status = IB_SUCCESS;\r
-       ib_av_handle_t  h_av;\r
-       ib_av_attr_t    av_attr;\r
-       cl_list_item_t  *p_list_item;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       cl_spinlock_acquire( &p_port_cm->lock );\r
-\r
-       /* Search for an existing AV that can be used. */\r
-       for( p_list_item = cl_qlist_head( &p_port_cm->av_list );\r
-                p_list_item != cl_qlist_end( &p_port_cm->av_list );\r
-                p_list_item = cl_qlist_next( p_list_item ) )\r
-       {\r
-               h_av = PARENT_STRUCT( p_list_item, ib_av_t, list_item );\r
-\r
-               /* verify sl level */\r
-               if( p_mad->remote_sl != h_av->av_attr.sl )\r
-                       continue;\r
-\r
-               if( p_mad->grh_valid == FALSE )\r
-               {\r
-                       /* verify source */\r
-                       if( p_mad->path_bits != h_av->av_attr.path_bits )\r
-                               continue;\r
-\r
-                       /* verify destination */\r
-                       if( p_mad->remote_lid != h_av->av_attr.dlid )\r
-                               continue;\r
-               }\r
-               else\r
-               {\r
-                       /* verify source */\r
-                       if( cl_memcmp( &p_mad->p_grh->src_gid.raw,\r
-                                       &h_av->av_attr.grh.src_gid.raw,\r
-                                       sizeof(ib_gid_t) ) )\r
-                               continue;\r
-\r
-                       /* verify destination */\r
-                       if( cl_memcmp( &p_mad->p_grh->dest_gid.raw,\r
-                                       &h_av->av_attr.grh.dest_gid.raw,\r
-                                       sizeof(ib_gid_t) ) )\r
-                               continue;\r
-               }\r
-\r
-               ref_al_obj( &h_av->obj );\r
-               p_mad->h_av = h_av;\r
-               break;\r
-       }\r
-\r
-       cl_spinlock_release( &p_port_cm->lock );\r
-\r
-       if( p_list_item == cl_qlist_end( &p_port_cm->av_list ) )\r
-       {\r
-               /* Create a new AV. */\r
-               /* format av info */\r
-               cl_memclr( &av_attr, sizeof(ib_av_attr_t) );\r
-               av_attr.sl = p_mad->remote_sl;\r
-               av_attr.static_rate = IB_PATH_RECORD_RATE_10_GBS;\r
-               av_attr.path_bits = p_mad->path_bits;\r
-               av_attr.dlid = p_mad->remote_lid;\r
-               av_attr.port_num = (uint8_t)( p_port_cm->port_idx + 1 );\r
-               av_attr.grh_valid = p_mad->grh_valid;\r
-               if( p_mad->grh_valid == TRUE )\r
-                       av_attr.grh = *p_mad->p_grh;\r
-\r
-               status = ib_create_av( p_port_cm->h_pd, &av_attr, &h_av );\r
-               if( status == IB_SUCCESS )\r
-               {\r
-                       /* take a reference on the object and add to av list */\r
-                       ref_al_obj( &h_av->obj );\r
-                       p_mad->h_av = h_av;\r
-                       cl_spinlock_acquire( &p_port_cm->lock );\r
-                       cl_qlist_insert_tail( &p_port_cm->av_list, &h_av->list_item );\r
-                       cl_spinlock_release( &p_port_cm->lock );\r
-               }\r
-       }\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return status;\r
-}\r
-\r
-ib_api_status_t\r
-__put_av(\r
-       IN                              cm_port_agent_t* const          p_port_cm,\r
-       IN                              ib_mad_element_t                        *p_mad )\r
-{\r
-       ib_av_t                 *h_av;\r
-       uint32_t                ref_cnt;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       h_av = p_mad->h_av;\r
-\r
-       CL_ASSERT( h_av );\r
-\r
-       /* Remove the reference on the AL object. */\r
-       cl_spinlock_acquire( &p_port_cm->lock );\r
-       ref_cnt = deref_al_obj( &h_av->obj );\r
-       CL_ASSERT( ref_cnt >= 1 );\r
-       if( ref_cnt == 1 )\r
-       {\r
-               cl_qlist_remove_item( &p_port_cm->av_list, &h_av->list_item );\r
-               cl_spinlock_release( &p_port_cm->lock );\r
-\r
-               ib_destroy_av( h_av );\r
-       }\r
-       else\r
-       {\r
-               cl_spinlock_release( &p_port_cm->lock );\r
-       }\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return IB_SUCCESS;\r
-}\r
-\r
-\r
-\r
-al_conn_t*\r
-__get_conn(\r
-       IN              const   ib_al_handle_t                  h_al,\r
-       IN              const   ib_qp_type_t                    qp_type )\r
-{\r
-       cl_pool_item_t  *p_item;\r
-       al_conn_t               *p_conn;\r
-       uint8_t                 counter;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-       CL_ASSERT( h_al && h_al->obj.type == AL_OBJ_TYPE_H_AL );\r
-\r
-       cl_spinlock_acquire( &gp_cm->obj.lock );\r
-       p_item = cl_qpool_get( &gp_cm->conn_pool );\r
-       if( !p_item )\r
-       {\r
-               cl_spinlock_release( &gp_cm->obj.lock );\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("cl_qpool_get failed for al_conn_t.\n") );\r
-               return NULL;\r
-       }\r
-\r
-       p_conn = PARENT_STRUCT( p_item, al_conn_t, map_item );\r
-\r
-       p_conn->p_req_info = cl_pool_get( &gp_cm->req_pool );\r
-       if( !p_conn->p_req_info )\r
-       {\r
-               cl_qpool_put( &gp_cm->conn_pool, (cl_pool_item_t*)&p_conn->map_item );\r
-               cl_spinlock_release( &gp_cm->obj.lock );\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("cl_pool_get failed for conn_req_t.\n") );\r
-               return NULL;\r
-       }\r
-       cl_spinlock_release( &gp_cm->obj.lock );\r
-\r
-       /*\r
-        * Increment the counter in the comm ID to meet REJ retry requirements\r
-        * from IB spec section 12.9.8.7\r
-        */\r
-       counter = (uint8_t)(p_conn->local_comm_id >> 24) + 1;\r
-       p_conn->local_comm_id &= CM_CONN_POOL_MAX_MASK;\r
-       p_conn->local_comm_id |= (((net32_t)counter) << 24);\r
-\r
-       /* Clear out the request information. */\r
-       cl_memclr( p_conn->p_req_info, sizeof(conn_req_t) );\r
-       p_conn->p_req_info->qp_mod_rtr.req_state = IB_QPS_RTR;\r
-       p_conn->p_req_info->qp_mod_rts.req_state = IB_QPS_RTS;\r
-       p_conn->p_req_info->port_idx = (uint8_t)-1;\r
-       p_conn->p_req_info->alt_port_idx = (uint8_t)-1;\r
-\r
-       /* Initialize the connection parameters. */\r
-       p_conn->ref_cnt = 1;\r
-\r
-       /* set version to highest known version */\r
-       p_conn->p_req_info->class_ver = IB_MCLASS_CM_VER_2;\r
-\r
-       p_conn->qp_type = qp_type;\r
-       p_conn->p_req_info->xport_type = qp_type;\r
-\r
-       p_conn->h_qp = NULL;\r
-\r
-       p_conn->local_qpn = 0;\r
-\r
-       p_conn->remote_qpn = 0;\r
-\r
-       /* init event based logic for synchronous operations */\r
-       p_conn->p_sync_event = NULL;\r
-\r
-       p_conn->pfn_cm_apr_cb = NULL;\r
-       p_conn->pfn_cm_drep_cb = NULL;\r
-       p_conn->pfn_cm_dreq_cb = NULL;\r
-       p_conn->pfn_cm_lap_cb = NULL;\r
-\r
-       p_conn->remote_ca_guid = 0;\r
-       p_conn->remote_comm_id = 0;\r
-\r
-       cl_memclr( &p_conn->path, sizeof( ib_path_rec_t ) * 2 );\r
-\r
-       p_conn->state = CM_CONN_RESET;\r
-\r
-       p_conn->was_active = TRUE;\r
-       p_conn->target_ack_delay = 0;\r
-\r
-       /*\r
-        * Initialize the MAD header.  The only field that needs to be set\r
-        * is the attribute ID.\r
-        */\r
-       p_conn->mads.hdr.attr_mod = 0;\r
-       p_conn->mads.hdr.base_ver = 1;\r
-       p_conn->mads.hdr.class_spec = 0;\r
-       p_conn->mads.hdr.method = IB_MAD_METHOD_SEND;\r
-       p_conn->mads.hdr.mgmt_class = IB_MCLASS_COMM_MGMT;\r
-       p_conn->mads.hdr.resv = 0;\r
-       p_conn->mads.hdr.status = 0;\r
-       p_conn->mads.hdr.trans_id = (ib_net64_t)cl_hton32( p_conn->local_comm_id );\r
-\r
-       /* class version is set to the user's request */\r
-       p_conn->mads.hdr.class_ver = IB_MCLASS_CM_VER_2;\r
-\r
-       al_insert_conn( h_al, p_conn );\r
-       if( p_conn->hdl == AL_INVALID_HANDLE )\r
-       {\r
-               al_remove_conn( p_conn );\r
-               cl_spinlock_acquire( &gp_cm->obj.lock );\r
-               cl_pool_put( &gp_cm->req_pool, p_conn->p_req_info );\r
-               p_conn->p_req_info = NULL;\r
-               cl_qpool_put( &gp_cm->conn_pool, (cl_pool_item_t*)&p_conn->map_item );\r
-               cl_spinlock_release( &gp_cm->obj.lock );\r
-               AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("al_insert_conn failed for conn_req_t.\n") );\r
-               return NULL;\r
-       }\r
-\r
-       ref_al_obj( &gp_cm->obj );\r
-       AL_EXIT( AL_DBG_CM );\r
-       return p_conn;\r
-}\r
-\r
-void\r
-__ref_conn(\r
-       IN                              al_conn_t* const                        p_conn )\r
-{\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       cl_atomic_inc( &p_conn->ref_cnt );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-\r
-void\r
-cm_cleanup_conn(\r
-       IN              const   ib_cm_handle_t                          h_conn )\r
-{\r
-       /*\r
-        * Set the reference count to 1, then decrement it to force cleanup.\r
-        * Note that if we are in this function, the connection object has not\r
-        * been cleaned up properly.  We are simply trying to cleanup the best\r
-        * that we can now.\r
-        */\r
-       h_conn->ref_cnt = 1;\r
-       __deref_conn( h_conn );\r
-}\r
-\r
-\r
-\r
-void\r
-__deref_conn(\r
-       IN                              al_conn_t* const                        p_conn )\r
-{\r
-       ib_qp_handle_t  h_qp;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       /*\r
-        * Destruction of the connection object and unbinding it from the QP\r
-        * must be atomic.  The QP will try to destroy the connection object\r
-        * when the QP is destroyed.  We use the global CM lock to synchronize\r
-        * changes to the connection's QP handle.\r
-        */\r
-       cl_spinlock_acquire( &gp_cm->obj.lock );\r
-       if( !cl_atomic_dec( &p_conn->ref_cnt ) )\r
-       {\r
-               /* Free the connection request information. */\r
-               __release_req_info( p_conn );\r
-\r
-               /*\r
-                * Unbind the QP while holding the CM lock -- see above.\r
-                * Note that we should not have a QP if we are at this point.  The\r
-                * only way this can occur is if we did not properly cleanup the\r
-                * QP in some other code path (such as disconnection).\r
-                */\r
-               h_qp = p_conn->h_qp;\r
-               cm_unbind_qp( p_conn );\r
-               \r
-               /* Remove the connection from AL, if not already done. */\r
-               if( p_conn->h_al )\r
-                       al_remove_conn( p_conn );\r
-\r
-               /*\r
-                * The connection should be in the RESET state.  If it is not, then\r
-                * we have most likely timed out trying to cleanup the connection.\r
-                * Attempting to recover from such poor behavior now.\r
-                */\r
-               switch( p_conn->state )\r
-               {\r
-               case CM_CONN_REQ_RCVD:\r
-               case CM_CONN_REQ_SENT:\r
-               case CM_CONN_REQ_MRA_RCVD:\r
-               case CM_CONN_REQ_MRA_SENT:\r
-               case CM_CONN_REP_RCVD:\r
-               case CM_CONN_REP_SENT:\r
-               case CM_CONN_REP_MRA_RCVD:\r
-               case CM_CONN_REP_MRA_SENT:\r
-                       /* We're a pending connection. */\r
-                       cl_qlist_remove_item( &gp_cm->pending_list,\r
-                               (cl_list_item_t*)&p_conn->map_item );\r
-                       break;\r
-\r
-               case CM_CONN_ESTABLISHED:\r
-               case CM_CONN_LAP_RCVD:\r
-               case CM_CONN_LAP_SENT:\r
-               case CM_CONN_LAP_MRA_RCVD:\r
-               case CM_CONN_LAP_MRA_SENT:\r
-               case CM_CONN_DREQ_SENT:\r
-               case CM_CONN_DREQ_RCVD:\r
-               case CM_CONN_DREP_SENT:\r
-                       /* We're still in the connection map. */\r
-                       cl_qmap_remove_item( &gp_cm->conn_map, &p_conn->map_item );\r
-                       break;\r
-\r
-               case CM_CONN_TIMEWAIT:\r
-                       /* We're still in the time wait list. */\r
-                       cl_qlist_remove_item( &gp_cm->time_wait_list,\r
-                               (cl_list_item_t*)&p_conn->map_item );\r
-                       break;\r
-\r
-               default:\r
-                       /* We shouldn't be in any lists or maps. */\r
-                       break;\r
-               }\r
-\r
-               /* Return the connection object to the free pool. */\r
-               cl_qpool_put( &gp_cm->conn_pool,\r
-                       (cl_pool_item_t*)&p_conn->map_item );\r
-               cl_spinlock_release( &gp_cm->obj.lock );\r
-               \r
-               if( h_qp )\r
-               {\r
-                       /* We shouldn't have a QP at this point. */\r
-                       AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                               ("QP (%016I64x) still referenced by connection object\n", (LONG_PTR)h_qp) );\r
-                       cm_reset_qp( h_qp, 0 );\r
-                       deref_al_obj( &h_qp->obj );\r
-               }\r
-               deref_al_obj( &gp_cm->obj );\r
-       }\r
-       else\r
-       {\r
-               cl_spinlock_release( &gp_cm->obj.lock );\r
-       }\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-\r
-boolean_t\r
-__is_lid_valid(\r
-       IN                              ib_net16_t                                      lid,\r
-       IN                              ib_net16_t                                      port_lid,\r
-       IN                              uint8_t                                         lmc )\r
-{\r
-       uint16_t                lid1;\r
-       uint16_t                lid2;\r
-       uint16_t                path_bits;\r
-\r
-       if(lmc)\r
-       {\r
-               lid1 = CL_NTOH16(lid);\r
-               lid2 = CL_NTOH16(port_lid);\r
-               path_bits = 0;\r
-\r
-               if( lid1 < lid2 )\r
-                       return FALSE;\r
-\r
-               while( lmc-- )\r
-                       path_bits = (uint16_t)( (path_bits << 1) | 1 );\r
-\r
-               lid2 |= path_bits;\r
-\r
-               if( lid1 > lid2)\r
-                       return FALSE;\r
-       }\r
-       else\r
-       {\r
-               if (lid != port_lid)\r
-                       return FALSE;\r
-       }\r
-\r
-       return TRUE;\r
-}\r
-\r
-\r
-\r
-ib_api_status_t\r
-__cm_send(\r
-       IN                              cm_port_agent_t* const          p_port_cm,\r
-       IN                              al_conn_t* const                        p_conn )\r
-{\r
-       ib_mad_element_t        *p_mad;\r
-       ib_api_status_t         status;\r
-       ib_grh_t                        grh;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       CL_ASSERT( p_conn );\r
-\r
-       /* Get a MAD from the pool. */\r
-       status = ib_get_mad( p_port_cm->pool_key, MAD_BLOCK_SIZE, &p_mad );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("ib_get_mad failed with status %s.\n", ib_get_err_str(status)) );\r
-               return status;\r
-       }\r
-\r
-       /* Set the addressing information in the MAD. */\r
-       if( p_conn->path[p_conn->idx_primary].hop_flow_raw.val )\r
-       {\r
-               cl_memclr( &grh, sizeof( ib_grh_t ) );\r
-               p_mad->p_grh = &grh;\r
-               grh.ver_class_flow = ib_grh_set_ver_class_flow(\r
-                       1, p_conn->path[p_conn->idx_primary].tclass,\r
-                       ib_path_rec_flow_lbl( &p_conn->path[p_conn->idx_primary] ) );\r
-               grh.hop_limit =\r
-                       ib_path_rec_hop_limit( &p_conn->path[p_conn->idx_primary] );\r
-               grh.src_gid = p_conn->path[p_conn->idx_primary].sgid;\r
-               grh.dest_gid = p_conn->path[p_conn->idx_primary].dgid;\r
-       }\r
-       else\r
-       {\r
-               p_mad->p_grh = NULL;\r
-       }\r
-       p_mad->remote_sl =\r
-               ib_path_rec_sl( &p_conn->path[p_conn->idx_primary] );\r
-       p_mad->remote_lid = p_conn->path[p_conn->idx_primary].dlid;\r
-       p_mad->path_bits = 0;\r
-       p_mad->remote_qp = IB_QP1;\r
-       p_mad->send_opt = IB_SEND_OPT_SIGNALED;\r
-       p_mad->remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;\r
-       switch( p_conn->mads.hdr.attr_id )\r
-       {\r
-       case CM_REQ_ATTR_ID:\r
-       case CM_REP_ATTR_ID:\r
-       case CM_LAP_ATTR_ID:\r
-       case CM_DREQ_ATTR_ID:\r
-               /*\r
-                * REQ, REP, LAP, and DREQ are retried until either a response is\r
-                * received or the operation times out.\r
-                */\r
-               p_mad->resp_expected = TRUE;\r
-               p_mad->retry_cnt = p_conn->max_cm_retries;\r
-               p_mad->timeout_ms = p_conn->retry_timeout;\r
-               break;\r
-\r
-       default:\r
-               /*\r
-                * All other CM MADs are sent once, and repeated if the previous MAD\r
-                * is received again.\r
-                */\r
-               p_mad->resp_expected = FALSE;\r
-               p_mad->retry_cnt = 0;\r
-               p_mad->timeout_ms = 0;\r
-               break;\r
-       }\r
-\r
-       /* Copy the mad contents. */\r
-       cl_memcpy( p_mad->p_mad_buf, &p_conn->mads, MAD_BLOCK_SIZE );\r
-\r
-       /* Set the contexts. */\r
-       p_mad->context1 = p_conn;\r
-       p_mad->context2 = NULL;\r
-       /* reference the connection for which we are sending the MAD. */\r
-       __ref_conn( p_conn );\r
-\r
-       /* Store the mad service handle in the connection for cancelling. */\r
-       p_conn->h_mad_svc = p_port_cm->h_mad_svc;\r
-\r
-       /* Get AV for the send */\r
-       p_mad->h_av = NULL;\r
-       status = __get_av( p_port_cm, p_mad );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               __deref_conn( p_conn );\r
-               ib_put_mad( p_mad );\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("__get_av failed with status %s.\n", ib_get_err_str(status)) );\r
-               return status;\r
-       }\r
-\r
-       /* Fire in the hole! */\r
-       p_conn->p_send_mad = p_mad;\r
-       status = ib_send_mad( p_port_cm->h_mad_svc, p_mad, NULL );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               p_conn->p_send_mad = NULL;\r
-               __deref_conn( p_conn );\r
-               ib_put_mad( p_mad );\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("ib_send_mad failed with status %s.\n", ib_get_err_str(status)) );\r
-               return status;\r
-       }\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return IB_SUCCESS;\r
-}\r
-\r
-\r
-\r
-ib_api_status_t\r
-__cm_send_mad(\r
-       IN                              cm_port_agent_t* const          p_port_cm,\r
-       IN                              ib_mad_element_t* const         p_mad )\r
-{\r
-       ib_api_status_t         status;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       CL_ASSERT( p_port_cm );\r
-       CL_ASSERT( p_mad );\r
-       CL_ASSERT( !p_mad->resp_expected );\r
-\r
-       /* Use the mad's attributes already present */\r
-\r
-       /* Set the contexts. */\r
-       p_mad->context1 = NULL;\r
-       p_mad->context2 = NULL;\r
-\r
-       /* Get AV for the send */\r
-       if( !p_mad->h_av )\r
-       {\r
-               status = __get_av( p_port_cm, p_mad );\r
-               if( status != IB_SUCCESS )\r
-               {\r
-                       ib_put_mad( p_mad );\r
-                       AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                               ("__get_av failed with status %s.\n", ib_get_err_str(status)) );\r
-                       return status;\r
-               }\r
-       }\r
-\r
-       status = ib_send_mad( p_port_cm->h_mad_svc, p_mad, NULL );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               ib_put_mad( p_mad );\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("ib_send_mad failed with status %s.\n", ib_get_err_str(status)) );\r
-               return status;\r
-       }\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return IB_SUCCESS;\r
-}\r
-\r
-\r
-\r
-void\r
-__repeated_mad(\r
-       IN                              cm_port_agent_t* const          p_port_cm,\r
-       IN                              al_conn_t* const                        p_conn,\r
-       IN                              ib_mad_element_t* const         p_mad )\r
-{\r
-       ib_api_status_t status;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       CL_ASSERT( p_port_cm );\r
-       CL_ASSERT( p_conn );\r
-       CL_ASSERT( p_mad );\r
-\r
-       /* Repeat the last mad sent for the connection. */\r
-       cm_res_acquire( p_conn );\r
-       switch( p_conn->state )\r
-       {\r
-       case CM_CONN_REQ_SENT:\r
-               /*\r
-                * CM_CONN_REQ_SENT is only valid for peer requests that win\r
-                * the peer comparisson.\r
-                */\r
-               CL_ASSERT( p_conn->p_req_info->pfn_cm_req_cb );\r
-       case CM_CONN_REP_SENT:\r
-       case CM_CONN_ESTABLISHED:\r
-       case CM_CONN_DREQ_SENT:\r
-       case CM_CONN_DREP_SENT:\r
-       case CM_CONN_TIMEWAIT:\r
-               cl_memcpy( p_mad->p_mad_buf, &p_conn->mads, sizeof(mad_cm_req_t) );\r
-               p_mad->send_context1 = NULL;\r
-               p_mad->send_context2 = NULL;\r
-               status = __cm_send_mad( p_port_cm, p_mad );\r
-               if( status == IB_SUCCESS )\r
-                       break;\r
-\r
-               /* Failure.  Fall through. */\r
-\r
-       default:\r
-               /* Return the MAD to the mad pool */\r
-               ib_put_mad( p_mad );\r
-               break;\r
-       }\r
-       cm_res_release( p_conn );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-void\r
-__cm_mad_recv_cb(\r
-       IN                              ib_mad_svc_handle_t                     h_mad_svc,\r
-       IN                              void                                            *context,\r
-       IN                              ib_mad_element_t                        *p_mad )\r
-{\r
-       ib_mad_t                *p_hdr;\r
-       cm_async_mad_t  *p_async_mad;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       UNUSED_PARAM( h_mad_svc );\r
-\r
-       CL_ASSERT( p_mad->p_next == NULL );\r
-\r
-       p_hdr = (ib_mad_t*)p_mad->p_mad_buf;\r
-\r
-       p_async_mad = (cm_async_mad_t*)cl_zalloc( sizeof(cm_async_mad_t) );\r
-       if( !p_async_mad )\r
-       {\r
-               ib_put_mad( p_mad );\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("failed to cl_zalloc cm_async_mad_t (%d bytes)\n",\r
-                       sizeof(cm_async_mad_t)) );\r
-               return;\r
-       }\r
-\r
-       p_async_mad->p_port_cm = (cm_port_agent_t*)context;\r
-       p_async_mad->p_mad = p_mad;\r
-\r
-       switch( p_hdr->attr_id )\r
-       {\r
-       case CM_REQ_ATTR_ID:\r
-               p_async_mad->item.pfn_callback = __process_cm_req;\r
-               break;\r
-\r
-       case CM_MRA_ATTR_ID:\r
-               p_async_mad->item.pfn_callback = __process_cm_mra;\r
-               break;\r
-\r
-       case CM_REJ_ATTR_ID:\r
-               p_async_mad->item.pfn_callback = __process_cm_rej;\r
-               break;\r
-\r
-       case CM_REP_ATTR_ID:\r
-               p_async_mad->item.pfn_callback = __process_cm_rep;\r
-               break;\r
-\r
-       case CM_RTU_ATTR_ID:\r
-               p_async_mad->item.pfn_callback = __process_cm_rtu;\r
-               break;\r
-\r
-       case CM_DREQ_ATTR_ID:\r
-               p_async_mad->item.pfn_callback = __process_cm_dreq;\r
-               break;\r
-\r
-       case CM_DREP_ATTR_ID:\r
-               p_async_mad->item.pfn_callback = __process_cm_drep;\r
-               break;\r
-\r
-       case CM_LAP_ATTR_ID:\r
-               p_async_mad->item.pfn_callback = __process_cm_lap;\r
-               break;\r
-\r
-       case CM_APR_ATTR_ID:\r
-               p_async_mad->item.pfn_callback = __process_cm_apr;\r
-               break;\r
-\r
-       case CM_SIDR_REQ_ATTR_ID:\r
-               p_async_mad->item.pfn_callback = __process_cm_sidr_req;\r
-               break;\r
-\r
-       case CM_SIDR_REP_ATTR_ID:\r
-               p_async_mad->item.pfn_callback = __process_cm_sidr_rep;\r
-               break;\r
-\r
-       default:\r
-               cl_free( p_async_mad );\r
-               ib_put_mad( p_mad );\r
-               AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("Invalid CM MAD attribute ID.\n") );\r
-               return;\r
-       }\r
-\r
-       /* Queue the MAD for asynchronous processing. */\r
-       cl_async_proc_queue( gp_async_proc_mgr, &p_async_mad->item );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-void\r
-__cm_mad_send_cb(\r
-       IN                              ib_mad_svc_handle_t                     h_mad_svc,\r
-       IN                              void                                            *context,\r
-       IN                              ib_mad_element_t                        *p_mad )\r
-{\r
-       cm_async_mad_t  *p_async_mad;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       UNUSED_PARAM( h_mad_svc );\r
-       CL_ASSERT( p_mad->p_next == NULL );\r
-\r
-       p_async_mad = (cm_async_mad_t*)cl_zalloc( sizeof(cm_async_mad_t) );\r
-       if( !p_async_mad )\r
-       {\r
-               ib_put_mad( p_mad );\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("failed to cl_zalloc cm_async_mad_t (%d bytes)\n",\r
-                       sizeof(cm_async_mad_t)) );\r
-               return;\r
-       }\r
-\r
-       p_async_mad->p_port_cm = (cm_port_agent_t*)context;\r
-       p_async_mad->p_mad = p_mad;\r
-       p_async_mad->item.pfn_callback = __process_cm_send_comp;\r
-\r
-       /* Queue the MAD for asynchronous processing. */\r
-       cl_async_proc_queue( gp_async_proc_mgr, &p_async_mad->item );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-void\r
-__process_cm_send_comp(\r
-       IN                              cl_async_proc_item_t            *p_item )\r
-{\r
-       cm_async_mad_t          *p_async_mad;\r
-       cm_port_agent_t         *p_port_cm;\r
-       al_conn_t                       *p_conn;\r
-       ib_mad_element_t        *p_mad;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_async_mad = PARENT_STRUCT( p_item, cm_async_mad_t, item );\r
-       p_mad = p_async_mad->p_mad;\r
-       p_port_cm = p_async_mad->p_port_cm;\r
-       cl_free( p_async_mad );\r
-\r
-       p_conn = (ib_cm_handle_t)p_mad->context1;\r
-\r
-       /*\r
-        * The connection context is not set when performing immediate responses,\r
-        * such as repeating MADS.\r
-        */\r
-       if( !p_conn )\r
-       {\r
-               __put_av( p_port_cm, p_mad );\r
-               ib_put_mad( p_mad );\r
-               AL_EXIT( AL_DBG_CM );\r
-               return;\r
-       }\r
-\r
-       cm_res_acquire( p_conn );\r
-       switch( p_mad->status )\r
-       {\r
-       case IB_WCS_SUCCESS:\r
-       case IB_WCS_CANCELED:\r
-               if( p_conn->state == CM_CONN_REP_SENT )\r
-               {\r
-                       /*\r
-                        *  Free connection for UD types (SIDR)\r
-                        */\r
-                       //***TODO: Do something similar with UD in IB_TIMEOUT case.\r
-                       if( p_conn->qp_type == IB_QPT_UNRELIABLE_DGRM )\r
-                       {\r
-                               /* Move the connection from the pending list to the connection map. */\r
-                               cl_spinlock_acquire( &gp_cm->obj.lock );\r
-                               cl_qlist_remove_item( &gp_cm->pending_list,\r
-                                       (cl_list_item_t*)&p_conn->map_item );\r
-                               cl_spinlock_release( &gp_cm->obj.lock );\r
-\r
-                               __deref_conn( p_conn );\r
-                       }\r
-               }\r
-\r
-               /* Release the reference taken when sending. */\r
-               cm_res_release( p_conn );\r
-               __deref_conn( p_conn );\r
-               break;\r
-\r
-       case IB_WCS_TIMEOUT_RETRY_ERR:\r
-               /*\r
-                * Timeout.  No response received within allowable time.  Queue\r
-                * an async item to reject and call the user back.  We continue to\r
-                * hold the reference on p_conn from the send.\r
-                */\r
-               switch( p_conn->state )\r
-               {\r
-               case CM_CONN_REQ_SENT:\r
-               case CM_CONN_REP_SENT:\r
-                       p_conn->timeout_item.pfn_callback = __proc_conn_timeout;\r
-                       break;\r
-               case CM_CONN_LAP_SENT:\r
-                       p_conn->timeout_item.pfn_callback = __proc_lap_timeout;\r
-                       break;\r
-               case CM_CONN_DREQ_SENT:\r
-                       p_conn->timeout_item.pfn_callback = __proc_dconn_timeout;\r
-                       break;\r
-               default:\r
-                       p_conn->timeout_item.pfn_callback = NULL;\r
-                       break;\r
-               }\r
-\r
-               /* Process timeouts asynchronously - queue the callback. */\r
-               if( p_conn->timeout_item.pfn_callback )\r
-                       cl_async_proc_queue( gp_async_proc_mgr, &p_conn->timeout_item );\r
-\r
-               cm_res_release( p_conn );\r
-\r
-               /* Continue to hold the reference if we're processing a timeout. */\r
-               if( !p_conn->timeout_item.pfn_callback )\r
-                       __deref_conn( p_conn );\r
-               break;\r
-\r
-       default:\r
-               /* Some sort of error. */\r
-               //***TODO: What kind of errors can we get, and how do we handle them?\r
-\r
-               /* Release the reference taken when sending. */\r
-               cm_res_release( p_conn );\r
-               __deref_conn( p_conn );\r
-       }\r
-\r
-       __put_av( p_port_cm, p_mad );\r
-       ib_put_mad( p_mad );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-\r
-/*\r
- * Called when the HCA generates the communication established event.\r
- * This happens when a receive happens when in the RTR state.  For now, we\r
- * continue to wait until the RTU is received before transitioning the QP.\r
- * Doing this is not ideal, but should work in almost all cases, since\r
- * the REP and RTU will be retried, and avoids having to deal with unpleasant\r
- * race conditions.\r
- */\r
-void\r
-cm_conn_established(\r
-       IN                              al_conn_t* const                        p_conn )\r
-{\r
-       /* We ignore the callback since we use RTU as the trigger. */\r
-       UNUSED_PARAM( p_conn );\r
-}\r
-\r
-\r
-\r
-/*\r
- * Called when the HCA migrates to the alternate path.\r
- */\r
-void\r
-cm_conn_migrated(\r
-       IN                              al_conn_t* const                        p_conn )\r
-{\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       /* Update the index to the primary path. */\r
-       cm_res_acquire( p_conn );\r
-\r
-       /* Increment the index. */\r
-       p_conn->idx_primary++;\r
-       /* Only the lowest bit is valid (0 or 1). */\r
-       p_conn->idx_primary&=0x1;\r
-       cm_res_release( p_conn );\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-/*\r
- * Called when the HCA generates a communication established or APM event.\r
- */\r
-void\r
-cm_async_event_cb(\r
-       IN              const   ib_async_event_rec_t* const     p_event_rec )\r
-{\r
-       al_conn_qp_t*                   p_qp;\r
-\r
-       CL_ASSERT( p_event_rec );\r
-\r
-       p_qp =  (al_conn_qp_t* __ptr64)p_event_rec->context;\r
-\r
-       /*\r
-        * Make sure to check that the QP is still connected by verifying\r
-        * that we still reference a p_conn structure.  The QP may be being\r
-        * destroyed.\r
-        */\r
-\r
-       switch( p_event_rec->code )\r
-       {\r
-       case IB_AE_QP_COMM:\r
-               if( !p_qp->p_conn )\r
-                       break;\r
-               cm_conn_established( p_qp->p_conn );\r
-               break;\r
-\r
-       case IB_AE_QP_APM:\r
-               if( !p_qp->p_conn )\r
-                       break;\r
-               cm_conn_migrated( p_qp->p_conn );\r
-               break;\r
-\r
-       case IB_AE_QP_APM_ERROR:\r
-               //***TODO: Figure out how to handle these errors.\r
-               break;\r
-\r
-       default:\r
-               break;\r
-       }\r
-}\r
-\r
-\r
-void\r
-__cm_qp_event_cb(\r
-       IN                              ib_async_event_rec_t            *p_event_rec )\r
-{\r
-       UNUSED_PARAM( p_event_rec );\r
-\r
-       /*\r
-        * Most of the QP events are trapped by the real owner of the QP.\r
-        * For real events, the CM may not be able to do much anyways!\r
-        */\r
-}\r
-\r
-\r
-/***static***/ ib_api_status_t\r
-__init_data_svc(\r
-       IN                              cm_port_agent_t* const          p_port_cm,\r
-       IN              const   ib_port_attr_t* const           p_port_attr )\r
-{\r
-       ib_api_status_t         status;\r
-       cl_status_t                     cl_status;\r
-       ib_qp_create_t          qp_create;\r
-       ib_mad_svc_t            mad_svc;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       cl_status = cl_spinlock_init( &p_port_cm->lock );\r
-       if( cl_status != CL_SUCCESS )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("cl_spinlock_init failed\n") );\r
-               return ib_convert_cl_status( cl_status );\r
-       }\r
-\r
-       /*\r
-        * Create the PD alias.  We use the port CM's al_obj_t as the context\r
-        * to allow using deref_al_obj as the destroy callback.\r
-        */\r
-       status = ib_alloc_pd( p_port_cm->h_ca, IB_PDT_ALIAS, &p_port_cm->obj,\r
-               &p_port_cm->h_pd );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("ib_alloc_pd failed with status %s\n", ib_get_err_str(status)) );\r
-               return status;\r
-       }\r
-       /* Reference the port object on behalf of the PD. */\r
-       ref_al_obj( &p_port_cm->obj );\r
-\r
-       /* Create the MAD QP. */\r
-       cl_memclr( &qp_create, sizeof( ib_qp_create_t ) );\r
-       qp_create.qp_type = IB_QPT_QP1_ALIAS;\r
-       qp_create.rq_depth = CM_MAD_RQ_DEPTH;\r
-       qp_create.sq_depth = CM_MAD_SQ_DEPTH;\r
-       qp_create.rq_sge = CM_MAD_RQ_SGE;\r
-       qp_create.sq_sge = CM_MAD_SQ_SGE;\r
-       qp_create.sq_signaled = TRUE;\r
-       /*\r
-        * We use the port CM's al_obj_t as the context to allow using\r
-        * deref_al_obj as the destroy callback.\r
-        */\r
-       status = ib_get_spl_qp( p_port_cm->h_pd, p_port_attr->port_guid,\r
-               &qp_create, &p_port_cm->obj, __cm_qp_event_cb, &p_port_cm->pool_key,\r
-               &p_port_cm->h_qp );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("ib_get_spl_qp failed with status %s\n", ib_get_err_str(status)) );\r
-               return status;\r
-       }\r
-       /* Reference the port object on behalf of the QP. */\r
-       ref_al_obj( &p_port_cm->obj );\r
-\r
-       /* Create the MAD service. */\r
-       cl_memclr( &mad_svc, sizeof(mad_svc) );\r
-       mad_svc.mad_svc_context = p_port_cm;\r
-       mad_svc.pfn_mad_recv_cb = __cm_mad_recv_cb;\r
-       mad_svc.pfn_mad_send_cb = __cm_mad_send_cb;\r
-       mad_svc.support_unsol = TRUE;\r
-       mad_svc.mgmt_class = IB_MCLASS_COMM_MGMT;\r
-       mad_svc.mgmt_version = IB_MCLASS_CM_VER_2;\r
-       mad_svc.method_array[IB_MAD_METHOD_SEND] = TRUE;\r
-       status =\r
-               ib_reg_mad_svc( p_port_cm->h_qp, &mad_svc, &p_port_cm->h_mad_svc );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("ib_reg_mad_svc failed with status %s\n", ib_get_err_str(status)) );\r
-               return status;\r
-       }\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return IB_SUCCESS;\r
-}\r
-\r
-\r
-/*\r
- * Create a port agent for a given port.\r
- */\r
-/***static***/ ib_api_status_t\r
-__create_port_cm(\r
-       IN                              ib_pnp_port_rec_t                       *p_pnp_rec )\r
-{\r
-       cm_port_agent_t         *p_port_cm;\r
-       ib_api_status_t         status;\r
-       ib_port_attr_mod_t      port_attr_mod;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       /* calculate size of port_cm struct */\r
-       p_port_cm = (cm_port_agent_t*)cl_zalloc( sizeof(cm_port_agent_t) +\r
-               p_pnp_rec->p_ca_attr->size );\r
-       if( !p_port_cm )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("Failed to cl_zalloc port CM agent.\n") );\r
-               return IB_INSUFFICIENT_MEMORY;\r
-       }\r
-\r
-       construct_al_obj( &p_port_cm->obj, AL_OBJ_TYPE_CM );\r
-       cl_qlist_init( &p_port_cm->av_list );\r
-       cl_spinlock_construct( &p_port_cm->lock );\r
-\r
-       status = init_al_obj( &p_port_cm->obj, p_port_cm, TRUE,\r
-               __destroying_port_cm, NULL, __free_port_cm );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               __free_port_cm( &p_port_cm->obj );\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("init_al_obj failed with status %s.\n", ib_get_err_str(status)) );\r
-               return status;\r
-       }\r
-\r
-       /* Attach to the global CM object. */\r
-       status = attach_al_obj( &gp_cm->obj, &p_port_cm->obj );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               p_port_cm->obj.pfn_destroy( &p_port_cm->obj, NULL );\r
-               AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("attach_al_obj returned %s.\n", ib_get_err_str(status)) );\r
-               return status;\r
-       }\r
-\r
-       p_port_cm->port_idx =\r
-               (uint8_t)(p_pnp_rec->p_port_attr->port_num - 1);\r
-\r
-       /* cache required port attributes */\r
-       p_port_cm->p_ca_attr = (ib_ca_attr_t*)\r
-               (((uint8_t*)p_port_cm) + sizeof(cm_port_agent_t));\r
-\r
-       ib_copy_ca_attr( p_port_cm->p_ca_attr, p_pnp_rec->p_ca_attr );\r
-\r
-       /* Get a reference to the CA on which we are loading. */\r
-       p_port_cm->h_ca = acquire_ca( p_pnp_rec->p_ca_attr->ca_guid );\r
-       if( !p_port_cm->h_ca )\r
-       {\r
-               p_port_cm->obj.pfn_destroy( &p_port_cm->obj, NULL );\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("acquire_ca failed.\n") );\r
-               return IB_INVALID_GUID;\r
-       }\r
-\r
-       status = __init_data_svc( p_port_cm, p_pnp_rec->p_port_attr );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               p_port_cm->obj.pfn_destroy( &p_port_cm->obj, NULL );\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("__init_data_svc failed with status %s.\n",\r
-                       ib_get_err_str(status)) );\r
-               return status;\r
-       }\r
-\r
-       /* Update local port attributes */\r
-       cl_memclr( &port_attr_mod, sizeof(ib_port_attr_mod_t) );\r
-       port_attr_mod.cap.cm = TRUE;\r
-       status = ib_modify_ca( p_port_cm->h_ca, p_pnp_rec->p_port_attr->port_num,\r
-               IB_CA_MOD_IS_CM_SUPPORTED, &port_attr_mod );\r
-\r
-       /* Update the PNP context to reference this port. */\r
-       p_pnp_rec->pnp_rec.context = p_port_cm;\r
-\r
-       /* Release the reference taken in init_al_obj. */\r
-       deref_al_obj( &p_port_cm->obj );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return IB_SUCCESS;\r
-}\r
-\r
-void\r
-__refresh_port_cm(\r
-       IN                              ib_pnp_port_rec_t                       *p_pnp_rec )\r
-{\r
-       cm_port_agent_t *p_port_cm;\r
-\r
-       CL_ASSERT( p_pnp_rec->pnp_rec.context );\r
-\r
-       p_port_cm = (cm_port_agent_t* __ptr64)p_pnp_rec->pnp_rec.context;\r
-       if( !p_port_cm )\r
-               return;\r
-\r
-       if( p_pnp_rec->p_ca_attr )\r
-       {\r
-               CL_ASSERT( p_port_cm->p_ca_attr->size == p_pnp_rec->p_ca_attr->size );\r
-               ib_copy_ca_attr( p_port_cm->p_ca_attr, p_pnp_rec->p_ca_attr );\r
-       }\r
-}\r
-\r
-/*\r
- * PnP callback for port event notifications.\r
- */\r
-/***static***/ ib_api_status_t\r
-__cm_pnp_cb(\r
-       IN                              ib_pnp_rec_t                            *p_pnp_rec )\r
-{\r
-       ib_api_status_t         status = IB_SUCCESS;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       switch( p_pnp_rec->pnp_event )\r
-       {\r
-       case IB_PNP_PORT_ADD:\r
-               /* Create the port agent. */\r
-               CL_ASSERT( !p_pnp_rec->context );\r
-               status = __create_port_cm( (ib_pnp_port_rec_t*)p_pnp_rec );\r
-               break;\r
-\r
-       case IB_PNP_PORT_ACTIVE:\r
-               /* refresh cache. */\r
-               __refresh_port_cm( (ib_pnp_port_rec_t*)p_pnp_rec );\r
-               break;\r
-\r
-       case IB_PNP_PORT_REMOVE:\r
-               CL_ASSERT( p_pnp_rec->context );\r
-\r
-               /* Destroy the port agent. */\r
-               ref_al_obj( &((cm_port_agent_t* __ptr64)p_pnp_rec->context)->obj );\r
-               ((cm_port_agent_t* __ptr64)p_pnp_rec->context)->obj.pfn_destroy(\r
-                       &((cm_port_agent_t* __ptr64)p_pnp_rec->context)->obj, NULL );\r
-\r
-               /* Fall through to validate the listen requests. */\r
-               break;\r
-       case IB_PNP_PORT_DOWN:\r
-       case IB_PNP_PKEY_CHANGE:\r
-       case IB_PNP_GID_CHANGE:\r
-       case IB_PNP_LID_CHANGE:\r
-               /*\r
-                * Validate listen requests. Due to the potential lack of port\r
-                * attributes (when a port is removed), it is not possible to\r
-                * invalidate requests.  Instead, we validate all requests and\r
-                * fail any that are not valid on any exitsting ports.\r
-                */\r
-               __refresh_port_cm( (ib_pnp_port_rec_t*)p_pnp_rec );\r
-               __validate_listens();\r
-               break;\r
-\r
-       default:\r
-               break;  /* Ignore other PNP events. */\r
-       }\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return status;\r
-}\r
-\r
-/*\r
- * Timer async proc routine that locks and does the job\r
- */\r
-void\r
-__process_cm_timer(\r
-       IN                              cl_async_proc_item_t            *p_item )\r
-{\r
-       //*** TODO: Timer callback must handle retries, timeouts, and time wait.\r
-       al_conn_t                               *p_conn;\r
-       cm_async_timer_t                *p_async_timer;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_async_timer = PARENT_STRUCT( p_item, cm_async_timer_t, item );\r
-       p_conn = p_async_timer->p_conn;\r
-\r
-       cm_res_acquire( p_conn );\r
-       switch( p_conn->state )\r
-       {\r
-       case CM_CONN_REQ_MRA_RCVD:\r
-       case CM_CONN_REP_MRA_RCVD:\r
-               {\r
-                       /*\r
-                        * Format the reject record before aborting the connection since\r
-                        * we need the QP context.\r
-                        */\r
-                       ib_cm_rej_rec_t                 rej_rec;\r
-                       cl_memclr( &rej_rec, sizeof( ib_cm_rej_rec_t ) );\r
-                       rej_rec.h_qp = p_conn->h_qp;\r
-                       rej_rec.qp_context = p_conn->h_qp->obj.context;\r
-                       rej_rec.rej_status = IB_REJ_TIMEOUT;\r
-\r
-                       /* Report the timeout and send the REJ. */\r
-                       __conn_reject( p_conn, IB_REJ_TIMEOUT, NULL, 0, NULL );\r
-                       cm_res_release( p_conn );\r
-\r
-                       p_conn->pfn_cm_rej_cb( &rej_rec );\r
-               }\r
-               break;\r
-\r
-       case CM_CONN_LAP_MRA_RCVD:\r
-               {\r
-                       /* Report the timeout. */\r
-                       ib_cm_apr_rec_t         apr_rec;\r
-                       cl_memclr( &apr_rec, sizeof( ib_cm_apr_rec_t ) );\r
-                       apr_rec.h_qp = p_conn->h_qp;\r
-                       apr_rec.qp_context = p_conn->h_qp->obj.context;\r
-                       apr_rec.cm_status = IB_TIMEOUT;\r
-                       apr_rec.apr_status = IB_AP_REJECT;\r
-\r
-                       /* Return to the established state. */\r
-                       p_conn->state = CM_CONN_ESTABLISHED;\r
-                       cm_res_release( p_conn );\r
-\r
-                       /* Notify the user that the LAP failed. */\r
-                       p_conn->pfn_cm_apr_cb( &apr_rec );\r
-               }\r
-               break;\r
-\r
-       //***TODO: Check synchronization issues relating to the timer being part\r
-       //***TODO: of the connection object.  Only timewait has potential issues.\r
-       //***TODO: If when destroying all connections in the timewait state the\r
-       //***TODO: timers are trimmed to zero, the destruction should be able to\r
-       //***TODO: wait until all timers expire.\r
-       case CM_CONN_TIMEWAIT:\r
-               p_conn->state = CM_CONN_RESET;\r
-               cl_spinlock_acquire( &gp_cm->obj.lock );\r
-               cl_qlist_remove_item( &gp_cm->time_wait_list,\r
-                       (cl_list_item_t*)&p_conn->map_item );\r
-               cl_spinlock_release( &gp_cm->obj.lock );\r
-               cm_res_release( p_conn );\r
-               break;\r
-\r
-       default:\r
-               /*\r
-                * No assert here, since the state could change just after the timer\r
-                * expires but before the callback is invoked.\r
-                */\r
-               cm_res_release( p_conn );\r
-               break;\r
-       }\r
-\r
-       /* Release the connection. */\r
-       __deref_conn( p_conn );\r
-       cl_free( p_async_timer );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-/*\r
- * Timer callback for taking connections out of the time wait state.\r
- */\r
-/***static***/ void\r
-__conn_timer_cb(\r
-       IN                              void                                            *context )\r
-{\r
-       cm_async_timer_t                *p_async_timer;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_async_timer = (cm_async_timer_t*)cl_zalloc( sizeof(cm_async_timer_t) );\r
-       if( !p_async_timer )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("failed to cl_zalloc cm_async_timer_t (%d bytes). System unstable!\n",\r
-                       sizeof(cm_async_timer_t)) );\r
-               /* Bah - just release the connection now. */\r
-               __deref_conn( (al_conn_t*)context );\r
-               return;\r
-       }\r
-\r
-       /*\r
-        * Queue an async item for further processing.  We are still holding a\r
-        * reference on the gp_cm.\r
-        */\r
-       p_async_timer->p_conn = (al_conn_t*)context;\r
-       p_async_timer->item.pfn_callback = __process_cm_timer;\r
-       cl_async_proc_queue( gp_async_proc_mgr, &p_async_timer->item );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-\r
-/*\r
- * Constructor for connection objects, called by the qpool when allocating new\r
- * connection objects.\r
- */\r
-/***static***/ cl_status_t\r
-__conn_ctor(\r
-       IN                              void* const                                     p_object,\r
-       IN                              void*                                           context,\r
-               OUT                     cl_pool_item_t** const          pp_pool_item )\r
-{\r
-       cl_status_t                     cl_status;\r
-       al_conn_t*                      p_conn = (al_conn_t*)p_object;\r
-\r
-       UNUSED_PARAM( context );\r
-\r
-       cl_status = cm_res_init( p_conn );\r
-       if( cl_status != CL_SUCCESS )\r
-       {\r
-               /*AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("cm_res_init failed with status %s.\n",\r
-                       CL_STATUS_MSG( cl_status )) );*/\r
-               return CL_ERROR;\r
-       }\r
-\r
-       cl_status = cl_timer_init( &p_conn->timer, __conn_timer_cb, p_conn );\r
-       if( cl_status != CL_SUCCESS )\r
-       {\r
-               /*AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("cl_timer_init failed with status %s.\n",\r
-                       CL_STATUS_MSG( cl_status )) );*/\r
-               cm_res_destroy( p_conn );\r
-               return cl_status;\r
-       }\r
-\r
-       p_conn->state = CM_CONN_RESET;\r
-       p_conn->local_comm_id = (net32_t)cl_atomic_inc( &local_comm_id );\r
-       /* Preset the top byte of the communication ID. */\r
-       p_conn->local_comm_id |= (net32_t)(cl_get_time_stamp() << 24);\r
-\r
-       *pp_pool_item = (cl_pool_item_t*)&p_conn->map_item;\r
-\r
-       return CL_SUCCESS;\r
-}\r
-\r
-\r
-\r
-/*\r
- * Destructor for connection objects, called by the qpool when freeing memory\r
- * allocated for a connection object.\r
- */\r
-/***static***/ void\r
-__conn_dtor(\r
-       IN              const   cl_pool_item_t* const           p_pool_item,\r
-       IN                              void*                                           context )\r
-{\r
-       al_conn_t                       *p_conn;\r
-\r
-       UNUSED_PARAM( context );\r
-\r
-       p_conn = PARENT_STRUCT( p_pool_item, al_conn_t, map_item );\r
-\r
-       /* Destroy the timer. */\r
-       cl_timer_destroy( &p_conn->timer );\r
-\r
-       /* Destroy the lock/mutex. */\r
-       cm_res_destroy( p_conn );\r
-}\r
-\r
-\r
-/*\r
- * Allocates and initialized the global CM agent.\r
- */\r
-ib_api_status_t\r
-create_cm(\r
-       IN                              al_obj_t* const                         p_parent_obj )\r
-{\r
-       ib_api_status_t         status;\r
-       cl_status_t                     cl_status;\r
-       ib_pnp_req_t            pnp_req;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       CL_ASSERT( gp_cm == NULL );\r
-\r
-       /* Allocate the global CM agent. */\r
-       gp_cm = (al_cm_agent_t*)cl_zalloc( sizeof(al_cm_agent_t) );\r
-       if( !gp_cm )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("Failed allocation of global CM agent.\n") );\r
-               return IB_INSUFFICIENT_MEMORY;\r
-       }\r
-\r
-       construct_al_obj( &gp_cm->obj, AL_OBJ_TYPE_CM );\r
-       cl_qpool_construct( &gp_cm->conn_pool );\r
-       cl_pool_construct( &gp_cm->req_pool );\r
-       cl_qlist_init( &gp_cm->active_listen_list );\r
-       cl_qlist_init( &gp_cm->inactive_listen_list );\r
-       cl_qlist_init( &gp_cm->pending_list );\r
-       cl_qmap_init( &gp_cm->conn_map );\r
-       cl_qlist_init( &gp_cm->time_wait_list );\r
-\r
-       status = init_al_obj( &gp_cm->obj, NULL, TRUE, __destroying_cm, NULL,\r
-               __free_cm );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               __free_cm( &gp_cm->obj );\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("init_al_obj failed with status %s.\n", ib_get_err_str(status)) );\r
-               return status;\r
-       }\r
-       /* Attach to the parent object. */\r
-       status = attach_al_obj( p_parent_obj, &gp_cm->obj );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               gp_cm->obj.pfn_destroy( &gp_cm->obj, NULL );\r
-               AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("attach_al_obj returned %s.\n", ib_get_err_str(status)) );\r
-               return status;\r
-       }\r
-\r
-       cl_status = cl_qpool_init( &gp_cm->conn_pool,\r
-               CM_CONN_POOL_MIN, CM_CONN_POOL_MAX, CM_CONN_POOL_GROW,\r
-               sizeof(al_conn_t), __conn_ctor, __conn_dtor, NULL );\r
-       if( cl_status != CL_SUCCESS )\r
-       {\r
-               gp_cm->obj.pfn_destroy( &gp_cm->obj, NULL );\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("cl_qpool_init failed with status %s.\n",\r
-                       CL_STATUS_MSG(cl_status)) );\r
-               return ib_convert_cl_status( cl_status );\r
-       }\r
-\r
-       cl_status = cl_pool_init( &gp_cm->req_pool, CM_REQ_POOL_MIN, 0,\r
-               CM_REQ_POOL_GROW, sizeof(conn_req_t), NULL, NULL, NULL );\r
-       if( cl_status != CL_SUCCESS )\r
-       {\r
-               gp_cm->obj.pfn_destroy( &gp_cm->obj, NULL );\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("cl_pool_init failed with status %s.\n",\r
-                       CL_STATUS_MSG(cl_status)) );\r
-               return ib_convert_cl_status( cl_status );\r
-       }\r
-\r
-       /* Register for port PnP notifications. */\r
-       cl_memclr( &pnp_req, sizeof(pnp_req) );\r
-       pnp_req.pnp_class = IB_PNP_PORT;\r
-       pnp_req.pfn_pnp_cb = __cm_pnp_cb;\r
-       status = ib_reg_pnp( gh_al, &pnp_req, &gp_cm->h_pnp );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               gp_cm->obj.pfn_destroy( &gp_cm->obj, NULL );\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("ib_reg_pnp failed with status %s.\n", ib_get_err_str(status)) );\r
-               return status;\r
-       }\r
-\r
-       /*\r
-        * Leave the reference taken in init_al_obj oustanding since PnP\r
-        * deregistration is asynchronous.  This replaces a call to ref and\r
-        * deref the object.\r
-        */\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return IB_SUCCESS;\r
-}\r
-\r
-\r
-\r
-ib_api_status_t\r
-__get_port_attr(\r
-       IN              const   ib_gid_t* const                         p_gid,\r
-       IN              const   ib_net16_t                                      lid,\r
-               OUT                     cm_port_agent_t** const         pp_port_cm OPTIONAL,\r
-               OUT                     ib_ca_attr_t** const            pp_ca_attr OPTIONAL )\r
-{\r
-       cl_list_item_t          *p_item;\r
-       cm_port_agent_t         *p_port_cm;\r
-       ib_api_status_t         status = IB_INVALID_SETTING;\r
-       ib_ca_attr_t            *p_ca_attr;\r
-       ib_port_attr_t          *p_port_attr;\r
-       uint16_t                        gid_idx;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       cl_spinlock_acquire( &gp_cm->obj.lock );\r
-       for( p_item = cl_qlist_head( &gp_cm->obj.obj_list );\r
-               p_item != cl_qlist_end( &gp_cm->obj.obj_list );\r
-               p_item = cl_qlist_next( p_item ) )\r
-       {\r
-               p_port_cm = PARENT_STRUCT(\r
-                       PARENT_STRUCT( p_item, al_obj_t, pool_item ),\r
-                       cm_port_agent_t, obj );\r
-\r
-               p_ca_attr = p_port_cm->p_ca_attr;\r
-\r
-               /* Shortcut to the port attributes for cleaner code. */\r
-               p_port_attr = &p_ca_attr->p_port_attr[p_port_cm->port_idx];\r
-\r
-               for( gid_idx = 0; gid_idx < p_port_attr->num_gids; gid_idx++ )\r
-               {\r
-                       if( cl_memcmp( &p_port_attr->p_gid_table[gid_idx],\r
-                               p_gid, sizeof(ib_gid_t) ) )\r
-                       {\r
-                               continue;\r
-                       }\r
-\r
-                       /* Found a GID match.  Look for LID match. */\r
-                       if( __is_lid_valid( lid, p_port_attr->lid,\r
-                                                               p_port_attr->lmc ) != TRUE )\r
-                       {\r
-                               continue;\r
-                       }\r
-\r
-                       /* Chaa-ching!  We have a winner! */\r
-                       cl_spinlock_release( &gp_cm->obj.lock );\r
-                       if( pp_ca_attr )\r
-                               *pp_ca_attr = p_ca_attr;\r
-\r
-                       if( pp_port_cm )\r
-                               *pp_port_cm = p_port_cm;\r
-\r
-                       AL_EXIT( AL_DBG_CM );\r
-                       return IB_SUCCESS;\r
-               }\r
-\r
-               /* No match. Reset the port cm pointer. */\r
-               status = IB_INVALID_SETTING;\r
-       }\r
-       cl_spinlock_release( &gp_cm->obj.lock );\r
-\r
-       AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-               ("No match found.\n") );\r
-       return status;\r
-}\r
-\r
diff --git a/core/al/kernel/al_cm_conn.c b/core/al/kernel/al_cm_conn.c
deleted file mode 100644 (file)
index ff6a1dc..0000000
+++ /dev/null
@@ -1,5792 +0,0 @@
-/*\r
- * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
- * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. \r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- *     Redistribution and use in source and binary forms, with or\r
- *     without modification, are permitted provided that the following\r
- *     conditions are met:\r
- *\r
- *      - Redistributions of source code must retain the above\r
- *        copyright notice, this list of conditions and the following\r
- *        disclaimer.\r
- *\r
- *      - Redistributions in binary form must reproduce the above\r
- *        copyright notice, this list of conditions and the following\r
- *        disclaimer in the documentation and/or other materials\r
- *        provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- * $Id$\r
- */\r
-\r
-#include <iba/ib_al.h>\r
-#include "al.h"\r
-#include "al_av.h"\r
-#include "al_ca.h"\r
-#include "al_cm.h"\r
-#include "al_cm_shared.h"\r
-#include "al_debug.h"\r
-#include "al_mgr.h"\r
-#include "al_qp.h"\r
-#include "al_verbs.h"\r
-#include "ib_common.h"\r
-\r
-\r
-extern al_cm_agent_t   *gp_cm;\r
-\r
-\r
-/*\r
- * See if a REQ is a duplicate.\r
- */\r
-cl_status_t\r
-__req_match_pending(\r
-       IN              const   cl_list_item_t* const           p_list_item,\r
-       IN                              void                                            *context )\r
-{\r
-       mad_cm_req_t            *p_req;\r
-       al_conn_t                       *p_conn;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       CL_ASSERT( p_list_item );\r
-       CL_ASSERT( context );\r
-\r
-       p_req = (mad_cm_req_t*)context;\r
-       p_conn = PARENT_STRUCT( p_list_item, al_conn_t, map_item );\r
-\r
-       if( p_req->local_comm_id != p_conn->remote_comm_id )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("Remote comm ID mismatch.\n") );\r
-               return CL_NOT_FOUND;\r
-       }\r
-\r
-       if( p_req->local_ca_guid != p_conn->remote_ca_guid )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("Remote CA GUID mismatch.\n") );\r
-               return CL_NOT_FOUND;\r
-       }\r
-\r
-       /* Reference the connection since we're working on it... */\r
-       __ref_conn( p_conn );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return CL_SUCCESS;\r
-}\r
-\r
-\r
-/*\r
- * See if message is for a connection that has already entered the timewait\r
- * state.\r
- */\r
-cl_status_t\r
-__match_timewait(\r
-       IN              const   cl_list_item_t* const           p_list_item,\r
-       IN                              void                                            *context )\r
-{\r
-       mad_cm_req_t            *p_req;\r
-       al_conn_t                       *p_conn;\r
-       conn_req_t                      *p_info;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       CL_ASSERT( p_list_item );\r
-       CL_ASSERT( context );\r
-\r
-       p_conn = PARENT_STRUCT( p_list_item, al_conn_t, map_item );\r
-       p_req = (mad_cm_req_t*)context;\r
-       p_info = PARENT_STRUCT( p_list_item, al_conn_t, map_item )->p_req_info;\r
-\r
-       if( p_conn->remote_ca_guid != p_req->local_ca_guid ||\r
-               conn_req_get_lcl_qpn( p_req ) != p_conn->remote_qpn )\r
-       {\r
-               AL_EXIT( AL_DBG_CM );\r
-               return CL_NOT_FOUND;\r
-       }\r
-\r
-       AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-               ("REQ received for stale connection.\n") );\r
-       return CL_SUCCESS;\r
-}\r
-\r
-\r
-/*\r
- * Search for a listening server.\r
- */\r
-cl_status_t\r
-__match_conn_listen(\r
-       IN              const   cl_list_item_t* const           p_list_item,\r
-       IN                              void                                            *context )\r
-{\r
-       mad_cm_req_t            *p_req;\r
-       al_listen_t                     *p_listen;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       CL_ASSERT( p_list_item );\r
-       CL_ASSERT( context );\r
-\r
-       p_req = (mad_cm_req_t*)context;\r
-       p_listen = PARENT_STRUCT( p_list_item, al_listen_t, list_item );\r
-\r
-       if( p_listen->info.qp_type == IB_QPT_UNRELIABLE_DGRM )\r
-               return CL_NOT_FOUND;\r
-\r
-       if( p_req->sid != p_listen->info.svc_id )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM, ("Svc ID mismatch.\n") );\r
-               return CL_NOT_FOUND;\r
-       }\r
-\r
-       if( p_listen->info.p_compare_buffer )\r
-       {\r
-               if( cl_memcmp( &p_req->pdata[p_listen->info.compare_offset],\r
-                       p_listen->info.p_compare_buffer, p_listen->info.compare_length ) )\r
-               {\r
-                       AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                               ("Svc ID match but compare buffer mismatch.\n") );\r
-                       return CL_NOT_FOUND;\r
-               }\r
-       }\r
-\r
-       /* Reference the listen so that it doesn't go away. */\r
-       ref_al_obj( &p_listen->obj );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return CL_SUCCESS;\r
-}\r
-\r
-\r
-/*\r
- * Try to find a matching peer-to-peer request.\r
- */\r
-cl_status_t\r
-__match_peer(\r
-       IN              const   cl_list_item_t* const           p_list_item,\r
-       IN                              void                                            *context )\r
-{\r
-       mad_cm_req_t            *p_req;\r
-       al_conn_t                       *p_conn;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       CL_ASSERT( p_list_item );\r
-       CL_ASSERT( context );\r
-\r
-       p_req = (mad_cm_req_t*)context;\r
-       p_conn = PARENT_STRUCT( p_list_item, al_conn_t, map_item );\r
-\r
-       /* Only match against peer-to-peer requests, not client requests. */\r
-       if( !p_conn->p_req_info->pfn_cm_req_cb )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM, ("Client request.\n") );\r
-               return CL_NOT_FOUND;\r
-       }\r
-\r
-       /* Validate the transport type against the connection's QP type. */\r
-       if( conn_req_get_qp_type( p_req ) != p_conn->h_qp->type )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("Transport type mismatch.\n") );\r
-               return CL_NOT_FOUND;\r
-       }\r
-\r
-       /* Compare SID and compare data. */\r
-       if( p_req->sid != p_conn->p_req_info->svc_id )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM, ("Svc ID mismatch.\n") );\r
-               return CL_NOT_FOUND;\r
-       }\r
-\r
-       if( p_conn->state != CM_CONN_REQ_SENT )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("Peer connection already matched.\n") );\r
-               return CL_NOT_FOUND;\r
-       }\r
-\r
-       /*\r
-        * Make sure the CA GUID and local comm ID are not the same\r
-        * so that a peer request doesn't match itself.\r
-        */\r
-       if( p_conn->p_req_info->p_ca_attr->ca_guid == p_req->local_ca_guid )\r
-       {\r
-               /* Trying to connect to the same CA as the request. */\r
-               if( p_conn->local_comm_id == p_req->local_comm_id )\r
-               {\r
-                       AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                               ("Same peer request.\n") );\r
-                       return CL_NOT_FOUND;\r
-               }\r
-       }\r
-\r
-       /* do a local lid and gid match */\r
-       if( p_conn->path->slid != p_req->primary_path.remote_lid )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("slid mismatch. May be a different req in list\n") );\r
-               return CL_NOT_FOUND;\r
-       }\r
-       if( cl_memcmp( &p_conn->path->sgid, &p_req->primary_path.remote_gid,\r
-               sizeof(ib_gid_t) ) )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("sgid mismatch. May be a different req in list\n") );\r
-               return CL_NOT_FOUND;\r
-       }\r
-\r
-       if( p_conn->path->dlid != p_req->primary_path.local_lid )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("dlid mismatch. May be a different req in list\n") );\r
-               return CL_NOT_FOUND;\r
-       }\r
-       if( cl_memcmp( &p_conn->path->dgid, &p_req->primary_path.local_gid,\r
-               sizeof(ib_gid_t) ) )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("dgid mismatch. May be a different req in list\n") );\r
-               return CL_NOT_FOUND;\r
-       }\r
-\r
-       /* compare private data */\r
-       if( p_conn->p_req_info->p_compare_buffer )\r
-       {\r
-               if( cl_memcmp( &p_req->pdata[p_conn->p_req_info->compare_offset],\r
-                       p_conn->p_req_info->p_compare_buffer,\r
-                       p_conn->p_req_info->compare_length ) )\r
-               {\r
-                       AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                               ("Svc ID match but compare buffer mismatch.\n") );\r
-                       return CL_NOT_FOUND;\r
-               }\r
-       }\r
-\r
-       /* Reference the connection object so it doesn't go away. */\r
-       __ref_conn( p_conn );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return CL_SUCCESS;\r
-}\r
-\r
-cl_status_t\r
-__match_conn_handoff(\r
-       IN              const   cl_list_item_t* const           p_list_item,\r
-       IN                              void                                            *context )\r
-{\r
-       al_conn_t                       *p_conn;\r
-       al_listen_t                     *p_listen;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       CL_ASSERT( p_list_item );\r
-       CL_ASSERT( context );\r
-\r
-       p_conn = (al_conn_t*)context;\r
-       p_listen = PARENT_STRUCT( p_list_item, al_listen_t, list_item );\r
-\r
-       if( p_listen->info.qp_type == IB_QPT_UNRELIABLE_DGRM )\r
-               return CL_NOT_FOUND;\r
-\r
-       if( p_conn->p_req_info->svc_id != p_listen->info.svc_id )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM, ("Svc ID mismatch.\n") );\r
-               return CL_NOT_FOUND;\r
-       }\r
-\r
-       if( p_listen->info.p_compare_buffer )\r
-       {\r
-               if( !p_conn->p_req_info->p_compare_buffer )\r
-               {\r
-                       AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                               ("Svc ID match but compare buffer mismatch.\n") );\r
-                       return CL_NOT_FOUND;\r
-               }\r
-               if( ( p_conn->p_req_info->compare_length !=\r
-                               p_listen->info.compare_length ) ||\r
-                       ( p_conn->p_req_info->compare_offset !=\r
-                               p_listen->info.compare_offset ) )\r
-               {\r
-                       AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                               ("Svc ID match but compare buffer mismatch.\n") );\r
-                       return CL_NOT_FOUND;\r
-               }\r
-               if( cl_memcmp( p_conn->p_req_info->p_compare_buffer,\r
-                       p_listen->info.p_compare_buffer, p_listen->info.compare_length ) )\r
-               {\r
-                       AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                               ("Svc ID match but compare buffer mismatch.\n") );\r
-                       return CL_NOT_FOUND;\r
-               }\r
-       }\r
-\r
-       /* Reference the listen so that it doesn't go away. */\r
-       ref_al_obj( &p_listen->obj );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return CL_SUCCESS;\r
-}\r
-\r
-\r
-\r
-/*\r
- * Migrate a connection request from the pending list to the\r
- * connection map.\r
- */\r
-static void\r
-__migrate_conn_to_map(\r
-       IN                              al_conn_t                                       *p_conn )\r
-{\r
-       uint64_t                key;\r
-\r
-       cl_spinlock_acquire( &gp_cm->obj.lock );\r
-       __release_req_info( p_conn );\r
-\r
-       cl_qlist_remove_item( &gp_cm->pending_list,\r
-               (cl_list_item_t*)&p_conn->map_item );\r
-\r
-       key = ((uint64_t)p_conn->local_comm_id << 32) |\r
-               ((uint64_t)p_conn->remote_comm_id);\r
-       cl_qmap_insert( &gp_cm->conn_map, key, &p_conn->map_item );\r
-\r
-       cl_spinlock_release( &gp_cm->obj.lock );\r
-}\r
-\r
-\r
-\r
-void\r
-__format_req_path_rec(\r
-       IN                              mad_cm_req_t                            *p_req,\r
-       IN                              req_path_info_t                         *p_path,\r
-               OUT                     ib_path_rec_t                           *p_path_rec )\r
-{\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       CL_ASSERT( p_req );\r
-       CL_ASSERT( p_path );\r
-       CL_ASSERT( p_path_rec );\r
-\r
-       /*\r
-        * Format a local path record. The local ack timeout specified in the\r
-        * REQ is twice the packet life plus the sender's CA ACK delay.  When\r
-        * reporting the packet life, we divide the local ack timeout by 2 to\r
-        * approach the path's packet lifetime.  Since local ack timeout is\r
-        * expressed as 4.096 * 2^x, subtracting 1 is equivalent to dividing the\r
-        * time in half.\r
-        */\r
-       ib_path_rec_init_local( p_path_rec,\r
-               &p_path->local_gid,\r
-               &p_path->remote_gid,\r
-               p_path->local_lid,\r
-               p_path->remote_lid,\r
-               1, p_req->pkey,\r
-               conn_req_path_get_svc_lvl( p_path ),\r
-               IB_PATH_SELECTOR_EXACTLY, conn_req_get_mtu( p_req ),\r
-               IB_PATH_SELECTOR_EXACTLY,\r
-               conn_req_path_get_pkt_rate( p_path ),\r
-               IB_PATH_SELECTOR_EXACTLY,\r
-               (uint8_t)( conn_req_path_get_lcl_ack_timeout( p_path ) - 1 ),\r
-               0 );\r
-\r
-       p_path_rec->hop_flow_raw.val = 0;\r
-       /* Add global routing info as necessary. */\r
-       if( !conn_req_path_get_subn_lcl( p_path ) )\r
-       {\r
-               ib_path_rec_set_hop_flow_raw( p_path_rec, p_path->hop_limit,\r
-                       conn_req_path_get_flow_lbl( p_path ), FALSE );\r
-               p_path_rec->tclass = p_path->traffic_class;\r
-       }\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-ib_rej_status_t\r
-__validate_req_2_listen_info(\r
-       IN                              cm_port_agent_t* const          p_port_cm,\r
-       IN                              al_listen_t* const                      p_listen,\r
-       IN                              ib_path_rec_t* const            p_path_rec )\r
-{\r
-       ib_port_attr_t  *p_port_attr;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_port_attr = &p_port_cm->p_ca_attr->p_port_attr[p_port_cm->port_idx];\r
-\r
-       /* match options set in the listen attributes */\r
-       if( ( p_listen->info.ca_guid != IB_ALL_CAS ) &&\r
-               ( p_listen->info.ca_guid != p_port_cm->p_ca_attr->ca_guid ) )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("CaGuid mismatch on listen.\n") );\r
-               return IB_REJ_INVALID_SID;\r
-       }\r
-\r
-       if( ( p_listen->info.lid != IB_ALL_LIDS ) &&\r
-               ( ( p_listen->info.lid != p_path_rec->slid ) ||\r
-                 ( p_listen->info.lid != p_port_attr->lid ) ) )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("lid mismatch on listen.\n") );\r
-               return IB_REJ_INVALID_LID;\r
-       }\r
-\r
-       if( ( p_listen->info.port_guid != IB_ALL_PORTS ) &&\r
-               ( p_listen->info.port_guid != p_port_attr->port_guid ) )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("PortGuid mismatch on listen.\n") );\r
-               return IB_REJ_INVALID_SID;\r
-       }\r
-\r
-       if( ( p_listen->info.pkey != IB_ALL_PKEYS ) &&\r
-               ( p_listen->info.pkey != p_path_rec->pkey ) )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("pkey mismatch on listen.\n") );\r
-               return IB_REJ_INVALID_SID;\r
-       }\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return 0;\r
-}\r
-\r
-\r
-ib_rej_status_t\r
-__format_req_rec(\r
-       IN                              cm_port_agent_t* const          p_port_cm,\r
-       IN                              mad_cm_req_t* const                     p_req,\r
-       IN                              al_listen_t* const                      p_listen        OPTIONAL,\r
-               OUT                     ib_cm_req_rec_t                         *p_req_rec )\r
-{\r
-       ib_rej_status_t rej_status;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       CL_ASSERT( p_port_cm );\r
-       CL_ASSERT( p_req );\r
-       CL_ASSERT( p_req_rec );\r
-\r
-       cl_memclr( p_req_rec, sizeof( ib_cm_req_rec_t ) );\r
-\r
-       /* validate version and transport type info */\r
-       switch( p_req->hdr.class_ver )\r
-       {\r
-       default:\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("Invalid class version type received.\n") );\r
-               return IB_REJ_UNSUPPORTED;\r
-\r
-       case IB_MCLASS_CM_VER_2:\r
-               break;\r
-       }\r
-       if( conn_req_get_qp_type( p_req ) > IB_QPT_UNRELIABLE_CONN )\r
-       {\r
-               /* Reserved value.  Reject. */\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("Invalid transport type received.\n") );\r
-               return IB_REJ_INVALID_XPORT;\r
-       }\r
-\r
-       /* format version specific data */\r
-       p_req_rec->p_req_pdata = p_req->pdata;\r
-\r
-       p_req_rec->qp_type = conn_req_get_qp_type( p_req );\r
-\r
-       p_req_rec->resp_res = conn_req_get_resp_res( p_req );\r
-       p_req_rec->flow_ctrl = conn_req_get_flow_ctrl( p_req );\r
-       p_req_rec->rnr_retry_cnt = conn_req_get_rnr_retry_cnt( p_req );\r
-\r
-       __format_req_path_rec( p_req, &p_req->primary_path,\r
-               &p_req_rec->primary_path );\r
-       __format_req_path_rec( p_req, &p_req->alternate_path,\r
-               &p_req_rec->alt_path );\r
-\r
-       /* validate a listen's inputs for ca, port or lid info */\r
-       if( p_listen )\r
-       {\r
-               rej_status = __validate_req_2_listen_info( p_port_cm, p_listen,\r
-                       &p_req_rec->primary_path );\r
-\r
-               if( rej_status )\r
-                       return rej_status;\r
-       }\r
-\r
-       /* These values are filled in later based on listen or peer connections\r
-       p_req_rec->context = ;\r
-       p_req_rec->h_cm_req = ;\r
-       p_req_rec->h_cm_listen = ;\r
-       */\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return 0;\r
-}\r
-\r
-\r
-void\r
-__reject_req(\r
-       IN                              cm_port_agent_t* const          p_port_cm,\r
-       IN                              ib_mad_element_t* const         p_mad,\r
-       IN              const   ib_rej_status_t                         reason )\r
-{\r
-       mad_cm_req_t    *p_req;\r
-       mad_cm_rej_t    *p_rej;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       CL_ASSERT( p_port_cm );\r
-       CL_ASSERT( p_mad );\r
-       CL_ASSERT( reason != 0 );\r
-\r
-       p_req = (mad_cm_req_t*)p_mad->p_mad_buf;\r
-       p_rej = (mad_cm_rej_t*)p_mad->p_mad_buf;\r
-\r
-       /*\r
-        * Format the reject information, overwriting the REQ data and send\r
-        * the response.\r
-        */\r
-       p_rej->hdr.attr_id = CM_REJ_ATTR_ID;\r
-       p_rej->remote_comm_id = p_req->local_comm_id;\r
-       p_rej->local_comm_id = 0;\r
-       conn_rej_set_msg_rejected( 0, p_rej );\r
-       p_rej->reason = reason;\r
-       conn_rej_set_ari( NULL, 0, p_rej );\r
-       conn_rej_set_pdata( NULL, 0, p_rej );\r
-       conn_rej_clr_rsvd_fields( p_rej );\r
-\r
-       /* Assumption: The retry count, send options, etc are zeroed on a recv. */\r
-       __cm_send_mad( p_port_cm, p_mad );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-/*\r
- * Validates the primary path specified for a connection, and stores\r
- * the assocated CA attributes and port index.\r
- */\r
-ib_api_status_t\r
-__validate_primary_path(\r
-       IN      OUT                     al_conn_t* const                        p_conn,\r
-               OUT                     cm_port_agent_t** const         pp_port_cm )\r
-{\r
-       ib_api_status_t         status;\r
-       cm_port_agent_t         *p_port_cm;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       CL_ASSERT( p_conn );\r
-       CL_ASSERT( pp_port_cm );\r
-       CL_ASSERT( p_conn->p_req_info );\r
-       CL_ASSERT( p_conn->h_qp );\r
-\r
-       /* Get the CA attributes for the paths requested. */\r
-       status = __get_port_attr( &p_conn->path[0].sgid, p_conn->path[0].slid,\r
-               &p_port_cm, &p_conn->p_req_info->p_ca_attr );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("__get_port_attr failed for primary path.\n") );\r
-               return status;\r
-       }\r
-       /* Check that the primary path is on the same CA as the QP. */\r
-       if( p_conn->p_req_info->p_ca_attr->ca_guid !=\r
-               p_conn->h_qp->obj.p_ci_ca->verbs.guid )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("Primary path is not on the same CA as QP.\n") );\r
-               return IB_INVALID_SETTING;\r
-       }\r
-\r
-       p_conn->p_req_info->port_idx = p_port_cm->port_idx;\r
-\r
-       *pp_port_cm = p_port_cm;\r
-       AL_EXIT( AL_DBG_CM );\r
-       return IB_SUCCESS;\r
-}\r
-\r
-\r
-/*\r
- * Validates the paths specified for a connection are valid, and stores\r
- * the assocated CA attributes and port indeces.\r
- */\r
-ib_api_status_t\r
-__validate_alt_path(\r
-       IN      OUT                     al_conn_t* const                        p_conn )\r
-{\r
-       ib_api_status_t         status;\r
-       cm_port_agent_t         *p_port_cm;\r
-       ib_ca_attr_t            *p_ca_attr;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       /* Get the alternate path port attributes. */\r
-       status = __get_port_attr( &p_conn->path[1].sgid, p_conn->path[1].slid,\r
-               &p_port_cm, &p_ca_attr );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("__get_port_attr failed for alternate path.\n") );\r
-               return status;\r
-       }\r
-       if( p_ca_attr->ca_guid != p_conn->p_req_info->p_ca_attr->ca_guid )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("Primary and alternate paths on different CAs.\n") );\r
-               return IB_INVALID_SETTING;\r
-       }\r
-       p_conn->p_req_info->alt_port_idx = p_port_cm->port_idx;\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return IB_SUCCESS;\r
-}\r
-\r
-\r
-/*\r
- * How the QP modify structures are populated for the RTR and RTS transitions:\r
- *\r
- *\r
- * The actual state transition to RTR and RTS is performed as per the IB spec.\r
- *\r
- * Matrix of the settings that are set for each MAD.\r
- *\r
- *                                                             |          REQ          |          REP          | RTU   | grp\r
- *                                                             | send  | recv  | send  | recv  | send  |\r
- * ----------------------------------------------------------------------------\r
- *     RTR     rq_psn                                  |       x       |               |       x       |               |               |       2\r
- *             dest_qp                                 |               |       x       |               |       x       |               |       3\r
- *             primary_av                              |               |               |               |               |               |\r
- *                     port_num                        |       x       |               |       x       |               |               |       2\r
- *                     sl                                      |       x       |       x       |               |               |               |       1\r
- *                     dlid                            |       x       |       x       |               |               |               |       1\r
- *                     grh                                     |       x       |       x       |               |               |               |       1\r
- *                     static_rate                     |       x       |       x       |               |               |               |       1\r
- *                     path_bits                       |       x       |               |       x       |               |               |       2\r
- *                     path_mtu                        |       x       |       x       |               |               |               |       1\r
- *                     local_ack_timeout       |               |       x       |               |       x       |               |       3\r
- *                     seq_err_retry_cnt       |       x       |       x       |               |               |               |       1\r
- *                     rnr_retry_cnt           |               |       x       |               |       x       |               |       3\r
- *             resp_res                                |               |  x(1) |       x       |       x       |               |  3,4\r
- *             alt_av                                  |               |               |               |               |               |\r
- *                     port_num                        |       x       |               |       x       |               |               |       2\r
- *                     sl                                      |       x       |       x       |               |               |               |       1\r
- *                     dlid                            |       x       |       x       |               |               |               |       1\r
- *                     grh                                     |       x       |       x       |               |               |               |       1\r
- *                     static_rate                     |       x       |       x       |               |               |               |       1\r
- *                     path_bits                       |       x       |               |       x       |               |               |       2\r
- *                     path_mtu                        |       x       |       x       |               |               |               |       1\r
- *                     local_ack_timeout       |               |       x       |               |       x       |               |       3\r
- *                     seq_err_retry_cnt       |       x       |       x       |               |               |               |       1\r
- *                     rnr_retry_cnt           |               |       x       |               |       x       |               |       3\r
- *             q_key                                   |               |  x(2) |               |  x(2) |               |       3\r
- *             pkey_index                              |       x       |               |       x       |               |               |       2\r
- *             access_ctrl                             |  *(5) |               |       x       |               |               |       2\r
- *             sq_depth                                |               |               |       x       |               |       x       |       5\r
- *             rq_depth                                |               |               |       x       |               |       x       |       5\r
- *             rnr_nak_timeout                 |  *(5) |               |       x       |               |               |       2\r
- * ----------------------------------------------------------------------\r
- *     RTS     sq_psn                                  |               |       x       |               |       x       |               |       3\r
- *             retry_cnt                               |       x       |       x       |               |               |               |       1\r
- *             rnr_retry_cnt                   |               |       x       |               |       x       |               |       3\r
- *             local_ack_timeout               |               |       x       |               |       x       |               |       3\r
- *             init_depth                              |               |               |       x       |       x       |               |       4\r
- *             qkey                                    |  (3)  |  (3)  |  (3)  |  (3)  |  (3)  |\r
- *             access_ctrl                             |               |               |               |               |       x       |       5\r
- *             resp_res                                |  (3)  |  (3)  |  (3)  |  (3)  |  (3)  |\r
- *             alt_av                                  |  (3)  |  (3)  |  (3)  |  (3)  |  (3)  |\r
- *             sq_depth                                |               |               |       x       |               |       x       |       5\r
- *             rq_depth                                |               |               |       x       |               |       x       |       5\r
- *             apm_state                               |               |               |       x       |       x       |               |       4\r
- *             primary_port                    |  (4)  |  (4)  |  (4)  |  (4)  |  (4)  |\r
- *             pkey_index                              |  (3)  |  (3)  |  (3)  |  (3)  |  (3)  |\r
- * ----------------------------------------------------------------------------\r
- * Notes:\r
- * (1) the responder resources are initialized to REQ.init_depth and then\r
- * scaled down when sending the REP if the local CA cannot support the\r
- * requested value.\r
- * (2) q_key is only used for RD and is not yet supported.\r
- * (3) handled in the RTR transition.\r
- * (4) handled in the INIT transition.\r
- * (5) set by CM to allow all operations.  Real value set at RTU time.\r
- */\r
-\r
-\r
-\r
-/*\r
- * + Validates the path information provided in the REQ and stores the\r
- *      associated CA attributes and port indeces.\r
- * + Transitions a connection object from active to passive in the peer case.\r
- * + Sets the path information in the connection and sets the CA GUID\r
- *      in the REQ callback record.\r
- */\r
-void\r
-__conn_save_wire_req(\r
-       IN              const   mad_cm_req_t* const                     p_req,\r
-               OUT                     al_conn_t*       const                  p_conn,\r
-       IN      OUT                     ib_cm_req_rec_t* const          p_req_rec )\r
-{\r
-       ib_qp_handle_t  h_qp;\r
-       struct _qp_rtr  *p_rtr;\r
-       struct _qp_rts  *p_rts;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_conn->state = CM_CONN_REQ_RCVD;\r
-       p_conn->was_active = FALSE;\r
-\r
-       /* Store pertinent information in the connection. */\r
-       p_conn->remote_comm_id = p_req->local_comm_id;\r
-       p_conn->remote_ca_guid = p_req->local_ca_guid;\r
-\r
-       p_conn->remote_qpn = conn_req_get_lcl_qpn( p_req );\r
-\r
-       /*\r
-        * Release the QP, if any, since the user can change the QP handles\r
-        * when replying.  This prevents the connection from being\r
-        * aborted if the user destroys a QP that was used to send the REQ for\r
-        * a peer-to-peer request that lost the peer comparisson.\r
-        */\r
-       h_qp = p_conn->h_qp;\r
-       if( h_qp )\r
-       {\r
-               cm_unbind_qp( p_conn );\r
-               deref_al_obj( &h_qp->obj );\r
-       }\r
-\r
-       /*\r
-        * Calculate the retry timeout.\r
-        * All timeout values in micro seconds are expressed as 4.096 * 2^x,\r
-        * where x is the timeout.  This approximates to 2^(x+2).\r
-        * Since we want milliseconds, we can further approximate to 2^(x-8).\r
-        * This results in a timeout that is roughly 5% on the low side, but\r
-        * good enough since OS timer resolutions are ~10ms.\r
-        */\r
-       if( conn_req_get_lcl_resp_timeout( p_req ) > 8 )\r
-       {\r
-               p_conn->retry_timeout =\r
-                       1 << (conn_req_get_lcl_resp_timeout( p_req ) - 8);\r
-\r
-               /* Minimum 10 ms timeout - picked to match typical OS timer resolution. */\r
-               if( p_conn->retry_timeout < 10 )\r
-                       p_conn->retry_timeout = 10;\r
-       }\r
-       else\r
-       {\r
-               p_conn->retry_timeout = 10;\r
-       }\r
-\r
-       /* Store the retry count. */\r
-       p_conn->max_cm_retries = conn_req_get_max_cm_retries( p_req );\r
-\r
-       /*\r
-        * Copy the paths from the req_rec into the connection for\r
-        * future use.\r
-        */\r
-       cl_memcpy( &p_conn->path[0], &p_req_rec->primary_path,\r
-               sizeof(ib_path_rec_t) );\r
-       cl_memcpy( &p_conn->path[1], &p_req_rec->alt_path, sizeof(ib_path_rec_t) );\r
-       p_conn->idx_primary = 0;\r
-\r
-       /* Setup the QP modify structures for the RTR and RTS transitions */\r
-       p_rtr = &p_conn->p_req_info->qp_mod_rtr.state.rtr;\r
-       p_rts = &p_conn->p_req_info->qp_mod_rts.state.rts;\r
-\r
-       /* Update RTR info */\r
-       p_rtr->dest_qp = conn_req_get_lcl_qpn( p_req );\r
-\r
-       /* The responder resources may be scaled down when sending the REP. */\r
-       p_rtr->resp_res = conn_req_get_init_depth( p_req );\r
-\r
-       /* updated in the REP\r
-       p_rtr->qkey;\r
-       p_rtr->access_ctrl;\r
-       p_rtr->sq_depth;\r
-       p_rtr->rq_depth;\r
-       p_rtr->rnr_nak_timeout;\r
-       p_rtr->primary_av;\r
-       p_rtr->alternate_av;\r
-       p_rtr->rq_psn;\r
-       */\r
-\r
-       /* Update RTS info */\r
-       p_rts->retry_cnt = conn_req_get_retry_cnt( p_req );\r
-       p_rts->rnr_retry_cnt = conn_req_get_rnr_retry_cnt( p_req );\r
-       p_rts->local_ack_timeout = conn_req_path_get_lcl_ack_timeout(\r
-               &p_req->primary_path );\r
-\r
-       p_rts->init_depth = conn_req_get_resp_res( p_req );\r
-\r
-       p_rts->opts = 0;\r
-       p_rts->resp_res = p_rtr->resp_res;\r
-       p_rts->sq_psn = conn_req_get_starting_psn( p_req );\r
-\r
-       /* Set in the REP\r
-       p_rts->rnr_nak_timeout;\r
-       p_rts->qkey;\r
-       p_rts->access_ctrl;\r
-       p_rts->sq_depth;\r
-       p_rts->rq_depth;\r
-       p_rts->apm_state;\r
-       p_rts->primary_port;\r
-       */\r
-\r
-       /* copy pdata for cm handoffs\r
-       cl_memcpy( p_conn->mads.req.pdata,\r
-               p_req->pdata, IB_REQ_PDATA_SIZE );*/\r
-\r
-       /* copy mad info for cm handoff */\r
-       p_conn->mads.req = *p_req;\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-void\r
-__listen_req(\r
-       IN                              cm_port_agent_t* const          p_port_cm,\r
-       IN                              al_listen_t* const                      p_listen,\r
-       IN                              ib_mad_element_t* const         p_mad )\r
-{\r
-       al_conn_t                       *p_conn;\r
-       mad_cm_req_t            *p_req;\r
-       ib_cm_req_rec_t         req_rec;\r
-       ib_rej_status_t         rej_status;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       CL_ASSERT( p_port_cm );\r
-       CL_ASSERT( p_listen );\r
-       CL_ASSERT( p_mad );\r
-\r
-       p_req = (mad_cm_req_t*)p_mad->p_mad_buf;\r
-\r
-       /* Format the callback record. */\r
-       rej_status = __format_req_rec( p_port_cm, p_req, p_listen, &req_rec );\r
-       if( rej_status )\r
-       {\r
-               /* The request is malformed.  Reject it. */\r
-               __reject_req( p_port_cm, p_mad, rej_status );\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("REJ sent for malformed REQ.\n") );\r
-               return;\r
-       }\r
-\r
-       /* Get a new connection object. */\r
-       p_conn = __get_conn( (ib_al_handle_t)p_listen->obj.p_parent_obj,\r
-               req_rec.qp_type );\r
-       if( !p_conn )\r
-       {\r
-               /* Reject the request for insufficient resources. */\r
-               __reject_req( p_port_cm, p_mad, IB_REJ_INSUF_RESOURCES );\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("REJ sent for insufficient resources.\n") );\r
-               return;\r
-       }\r
-\r
-       /* update p_conn from listen and req values. */\r
-       p_conn->p_req_info->pfn_cm_req_cb = NULL;\r
-       p_conn->pfn_cm_rej_cb = p_listen->info.pfn_cm_rej_cb;\r
-       p_conn->p_req_info->pfn_cm_rep_cb = NULL;\r
-       p_conn->pfn_cm_mra_cb = p_listen->info.pfn_cm_mra_cb;\r
-\r
-       p_conn->p_port_cm = p_port_cm;\r
-\r
-       /* update listen based rec */\r
-       req_rec.context = p_listen->obj.context;\r
-       req_rec.h_cm_req = p_conn;\r
-       req_rec.h_cm_listen = p_listen;\r
-\r
-       /* save req info received */\r
-       __conn_save_wire_req( p_req, p_conn, &req_rec );\r
-\r
-       /* Add the connection to the list of pending connections. */\r
-       cl_spinlock_acquire( &gp_cm->obj.lock );\r
-       cl_qlist_insert_tail( &gp_cm->pending_list,\r
-               (cl_list_item_t*)&p_conn->map_item );\r
-       cl_spinlock_release( &gp_cm->obj.lock );\r
-\r
-       /* Reference the connection object until the user calls REP or REJ. */\r
-       __ref_conn( p_conn );\r
-\r
-       /* Invoke the user's callback. */\r
-       p_listen->info.pfn_cm_req_cb( &req_rec );\r
-\r
-       /* Return the REQ to the mad pool */\r
-       ib_put_mad( p_mad );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-void\r
-__peer_req(\r
-       IN                              cm_port_agent_t* const          p_port_cm,\r
-       IN                              al_conn_t* const                        p_conn,\r
-       IN                              ib_mad_element_t* const         p_mad )\r
-{\r
-       mad_cm_req_t    *p_req;\r
-       ib_cm_req_rec_t req_rec;\r
-       ib_rej_status_t rej_status;\r
-       ib_api_status_t status;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       CL_ASSERT( p_port_cm );\r
-       CL_ASSERT( p_conn );\r
-       CL_ASSERT( p_conn->p_req_info );\r
-       /* Must be peer-to-peer. */\r
-       CL_ASSERT( p_conn->p_req_info->pfn_cm_req_cb );\r
-       CL_ASSERT( p_mad );\r
-       CL_ASSERT( p_conn->h_qp );\r
-\r
-       p_req = ib_get_mad_buf( p_mad );\r
-\r
-       cm_res_acquire( p_conn );\r
-\r
-       /* Perform peer comparison. */\r
-       if( cl_ntoh64( p_conn->p_req_info->p_ca_attr->ca_guid ) >\r
-               cl_ntoh64( p_req->local_ca_guid ) )\r
-       {\r
-               cm_res_release( p_conn );\r
-               __repeated_mad( p_port_cm, p_conn, p_mad );\r
-               /* Release reference on p_conn obtained from __match_peer. */\r
-               __deref_conn( p_conn );\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("Won peer compare, repeating REQ.\n") );\r
-               return;\r
-       }\r
-       if( cl_ntoh32( p_conn->p_req_info->local_qpn ) >\r
-               cl_ntoh32( conn_req_get_lcl_qpn( p_req ) ) )\r
-       {\r
-               cm_res_release( p_conn );\r
-               __repeated_mad( p_port_cm, p_conn, p_mad );\r
-               /* Release reference on p_conn obtained from __match_peer. */\r
-               __deref_conn( p_conn );\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("Won peer compare, repeating REQ.\n") );\r
-               return;\r
-       }\r
-\r
-       /* Format the callback record. */\r
-       rej_status = __format_req_rec( p_port_cm, p_req, NULL, &req_rec );\r
-       if( rej_status )\r
-       {\r
-               cm_res_release( p_conn );\r
-               /* Release reference on p_conn obtained from __match_peer. */\r
-               __deref_conn( p_conn );\r
-\r
-               /* The request is malformed.  Reject it. */\r
-               __reject_req( p_port_cm, p_mad, rej_status );\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("REJ sent for malformed REQ.\n") );\r
-               return;\r
-       }\r
-\r
-       /* Stop sending the REQ and change the state. */\r
-       status = ib_cancel_mad( p_conn->h_mad_svc, p_conn->p_send_mad );\r
-       p_conn->p_send_mad = NULL;\r
-       if( status == IB_NOT_FOUND )\r
-       {\r
-               cm_res_release( p_conn );\r
-               /* Release reference on p_conn obtained from __match_peer. */\r
-               __deref_conn( p_conn );\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("REQ in invalid state.\n") );\r
-               return;\r
-       }\r
-\r
-       /* update peer based rec handles and context values */\r
-       req_rec.context = p_conn->h_qp->obj.context;\r
-       req_rec.h_cm_req = p_conn;\r
-       req_rec.h_cm_listen = NULL;\r
-\r
-       __conn_save_wire_req(p_req, p_conn, &req_rec );\r
-       cm_res_release( p_conn );\r
-\r
-       /* Note that we're holding a reference on p_conn from __match_peer(). */\r
-\r
-       /* Invoke the user's callback.  User must call ib_cm_rep or ib_cm_rej. */\r
-       p_conn->p_req_info->pfn_cm_req_cb( &req_rec );\r
-\r
-       /* Return the REQ to the mad pool */\r
-       ib_put_mad( p_mad );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-ib_api_status_t\r
-cm_conn_handoff(\r
-       IN                              al_conn_t*       const                  p_conn,\r
-       IN              const   net64_t                                         svc_id )\r
-{\r
-       cl_list_item_t  *p_list_item;\r
-       al_listen_t             *p_listen;\r
-       ib_cm_req_rec_t req_rec;\r
-       ib_rej_status_t rej_status;\r
-       al_conn_t               *p_conn_handoff;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       CL_ASSERT( p_conn );\r
-\r
-       cm_res_acquire( p_conn );\r
-\r
-       /*\r
-        * To do a successful handoff the current connection's attribs should be\r
-        * validated against the service_id to be handed over to.\r
-        * We change the service_id of the current connection to the one we want\r
-        * to hand off to. The match routine will validate the rest of the handoff\r
-        * process.\r
-        */\r
-       p_conn->p_req_info->svc_id = svc_id;\r
-\r
-       cl_spinlock_acquire( &gp_cm->obj.lock );\r
-       p_list_item = cl_qlist_find_from_head( &gp_cm->active_listen_list,\r
-               __match_conn_handoff, p_conn );\r
-       if( p_list_item == cl_qlist_end( &gp_cm->active_listen_list ) )\r
-       {\r
-               cl_spinlock_release( &gp_cm->obj.lock );\r
-               __conn_reject( p_conn, IB_REJ_INVALID_SID, NULL, 0, NULL );\r
-               cm_res_release( p_conn );\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("Handoff failed on svc_id!\n") );\r
-               return IB_INVALID_PARAMETER;\r
-       }\r
-       cl_spinlock_release( &gp_cm->obj.lock );\r
-\r
-       /* A listen for handoff was found. Now transfer details from old conn */\r
-       p_listen = PARENT_STRUCT( p_list_item, al_listen_t, list_item );\r
-\r
-       /* Format the callback record. */\r
-       rej_status = __format_req_rec( p_conn->p_port_cm, &p_conn->mads.req,\r
-               p_listen, &req_rec );\r
-       if( rej_status )\r
-       {\r
-               /* The request does not conform to the handoff process service. */\r
-               __conn_reject( p_conn, rej_status, NULL, 0, NULL );\r
-               cm_res_release( p_conn );\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("Handoff failed on svc_id info!\n") );\r
-               return IB_INVALID_PARAMETER;\r
-       }\r
-\r
-       /* Get a new connection object. */\r
-       p_conn_handoff = __get_conn( (ib_al_handle_t)p_listen->obj.p_parent_obj,\r
-               req_rec.qp_type );\r
-       if( !p_conn_handoff )\r
-       {\r
-               /* Reject the request for insufficient resources. */\r
-               __conn_reject( p_conn, IB_REJ_INSUF_RESOURCES, NULL, 0, NULL );\r
-               cm_res_release( p_conn );\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("Handoff failed on insufficient resources.\n") );\r
-               return IB_INSUFFICIENT_MEMORY;\r
-       }\r
-\r
-       /* update p_conn from listen and req values. */\r
-       p_conn_handoff->p_req_info->pfn_cm_req_cb = NULL;\r
-       p_conn_handoff->pfn_cm_rej_cb = p_listen->info.pfn_cm_rej_cb;\r
-       p_conn_handoff->p_req_info->pfn_cm_rep_cb = NULL;\r
-       p_conn_handoff->pfn_cm_mra_cb = p_listen->info.pfn_cm_mra_cb;\r
-\r
-       p_conn_handoff->p_port_cm = p_conn->p_port_cm;\r
-\r
-       /* update listen based rec */\r
-       req_rec.context = p_listen->obj.context;\r
-       req_rec.h_cm_req = p_conn_handoff;\r
-       req_rec.h_cm_listen = p_listen;\r
-\r
-       /* save req info received */\r
-       __conn_save_wire_req( &p_conn->mads.req, p_conn_handoff, &req_rec );\r
-\r
-       /* Add the connection to the list of pending connections. */\r
-       cl_spinlock_acquire( &gp_cm->obj.lock );\r
-       cl_qlist_insert_tail( &gp_cm->pending_list,\r
-               (cl_list_item_t*)&p_conn_handoff->map_item );\r
-       cl_spinlock_release( &gp_cm->obj.lock );\r
-\r
-       /* Reference the connection object until the user calls REP or REJ. */\r
-       __ref_conn( p_conn_handoff );\r
-\r
-       /* Abort the original connection created when the REQ was received. */\r
-       __conn_abort( p_conn );\r
-       cm_res_release( p_conn );\r
-\r
-       /* Invoke the user's callback. */\r
-       p_listen->info.pfn_cm_req_cb( &req_rec );\r
-\r
-       /* deref the listen object */\r
-       deref_al_obj( &p_listen->obj );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return IB_SUCCESS;\r
-}\r
-\r
-\r
-void\r
-__process_cm_req(\r
-       IN                              cl_async_proc_item_t            *p_item )\r
-{\r
-       cm_port_agent_t *p_port_cm;\r
-       mad_cm_req_t    *p_req;\r
-       cm_async_mad_t  *p_async_mad;\r
-       cl_list_item_t  *p_list_item;\r
-       al_conn_t               *p_conn;\r
-       al_listen_t             *p_listen;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_async_mad = PARENT_STRUCT( p_item, cm_async_mad_t, item );\r
-       p_req = (mad_cm_req_t*)p_async_mad->p_mad->p_mad_buf;\r
-       p_port_cm = p_async_mad->p_port_cm;\r
-\r
-       AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_CM, ("REQ: comm_id (x%x) received\n",\r
-               p_req->local_comm_id ) );\r
-\r
-       /* Match against pending connections using remote comm ID and CA GUID. */\r
-       cl_spinlock_acquire( &gp_cm->obj.lock );\r
-       p_list_item = cl_qlist_find_from_head( &gp_cm->pending_list,\r
-               __req_match_pending, p_req );\r
-       if( p_list_item != cl_qlist_end( &gp_cm->pending_list ) )\r
-       {\r
-               /* Already received the REQ. */\r
-               cl_spinlock_release( &gp_cm->obj.lock );\r
-               p_conn = PARENT_STRUCT( p_list_item, al_conn_t, map_item );\r
-               __repeated_mad( p_port_cm, p_conn, p_async_mad->p_mad );\r
-               __deref_conn( p_conn );\r
-               cl_free( p_async_mad );\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("Duplicate REQ received.\n") );\r
-               return;\r
-       }\r
-\r
-       /* Match against stale connections using remote comm ID and CA GUID. */\r
-       p_list_item = cl_qlist_find_from_tail( &gp_cm->time_wait_list,\r
-               __match_timewait, p_req );\r
-       if( p_list_item != cl_qlist_end( &gp_cm->time_wait_list ) )\r
-       {\r
-               cl_spinlock_release( &gp_cm->obj.lock );\r
-               __reject_req( p_port_cm, p_async_mad->p_mad, IB_REJ_STALE_CONN );\r
-               cl_free( p_async_mad );\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("REQ received for connection in TIME_WAIT state.\n") );\r
-               return;\r
-       }\r
-\r
-       /* Match against listens using SID and compare data. */\r
-       p_list_item = cl_qlist_find_from_head( &gp_cm->active_listen_list,\r
-               __match_conn_listen, p_req );\r
-       if( p_list_item != cl_qlist_end( &gp_cm->active_listen_list ) )\r
-       {\r
-               cl_spinlock_release( &gp_cm->obj.lock );\r
-               p_listen = PARENT_STRUCT( p_list_item, al_listen_t, list_item );\r
-               __listen_req( p_port_cm, p_listen, p_async_mad->p_mad );\r
-               deref_al_obj( &p_listen->obj );\r
-               cl_free( p_async_mad );\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("REQ matched a listen.\n") );\r
-               return;\r
-       }\r
-\r
-       AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_CM, ("No listens active!\n") );\r
-\r
-       /* Match against peer-to-peer requests using SID and compare data. */\r
-       p_list_item = cl_qlist_find_from_head( &gp_cm->pending_list,\r
-               __match_peer, p_req );\r
-       if( p_list_item != cl_qlist_end( &gp_cm->pending_list ) )\r
-       {\r
-               cl_spinlock_release( &gp_cm->obj.lock );\r
-               p_conn = PARENT_STRUCT( p_list_item, al_conn_t, map_item );\r
-               __peer_req( p_port_cm, p_conn, p_async_mad->p_mad );\r
-               cl_free( p_async_mad );\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("REQ matched a peer-to-peer request.\n") );\r
-               return;\r
-       }\r
-\r
-       /* No match found.  Reject. */\r
-       cl_spinlock_release( &gp_cm->obj.lock );\r
-       __reject_req( p_port_cm, p_async_mad->p_mad, IB_REJ_INVALID_SID );\r
-       cl_free( p_async_mad );\r
-       AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-               ("REQ received but no match found.\n") );\r
-}\r
-\r
-\r
-/*\r
- * Matches a connection by local (and remote if available) communication ID.\r
- */\r
-cl_status_t\r
-__mra_match(\r
-       IN              const   cl_list_item_t* const           p_list_item,\r
-       IN                              void                                            *context )\r
-{\r
-       al_conn_t               *p_conn;\r
-       mad_cm_mra_t    *p_mra;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_conn = PARENT_STRUCT( p_list_item, al_conn_t, map_item );\r
-       p_mra = (mad_cm_mra_t*)context;\r
-\r
-       if( p_conn->local_comm_id != p_mra->remote_comm_id )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("Local conn ID mismatch.\n") );\r
-               return CL_NOT_FOUND;\r
-       }\r
-\r
-       if( p_conn->remote_comm_id &&\r
-               p_conn->remote_comm_id == p_mra->local_comm_id )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("Remote conn ID mismatch.\n") );\r
-               return CL_NOT_FOUND;\r
-       }\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return CL_SUCCESS;\r
-}\r
-\r
-\r
-void\r
-__start_mra_timer(\r
-       IN                              al_conn_t* const                        p_conn,\r
-       IN              const   mad_cm_mra_t* const                     p_mra )\r
-{\r
-       uint32_t                timeout;\r
-       uint8_t                 pkt_life;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       /* Cancel the send for the REQ, REP, or LAP. */\r
-       ib_cancel_mad( p_conn->h_mad_svc, p_conn->p_send_mad );\r
-       p_conn->p_send_mad = NULL;\r
-\r
-       /*\r
-        * Set the retry timer to the interval specified in the MRA.\r
-        * All timeout values in micro seconds are expressed as 4.096 * 2^x,\r
-        * where x is the timeout.  This approximates to 2^(x+2).\r
-        * Since we want milliseconds, we can further approximate to 2^(x-8).\r
-        * This results in a timeout that is roughly 5% on the low side, but\r
-        * good enough.\r
-        */\r
-       if( conn_mra_get_svc_timeout( p_mra ) > 8 )\r
-               timeout = 1 << (conn_mra_get_svc_timeout( p_mra ) - 8);\r
-       else\r
-               timeout = 0;\r
-\r
-       pkt_life = ib_path_rec_pkt_life( &p_conn->path[p_conn->idx_primary] );\r
-       if( pkt_life > 8 )\r
-               timeout += 1 << (pkt_life - 8);\r
-\r
-       /*\r
-        * Minimum 10 ms timeout - picked to match typical OS timer resolution.\r
-        */\r
-       if( timeout < 10 )\r
-               timeout = 10;\r
-       if( p_conn->state != CM_CONN_REQ_MRA_RCVD &&\r
-               p_conn->state != CM_CONN_REP_MRA_RCVD &&\r
-               p_conn->state != CM_CONN_LAP_MRA_RCVD )\r
-       {\r
-               /* Only reference the connection the first time we set the timer. */\r
-               __ref_conn( p_conn );\r
-       }\r
-\r
-       if( cl_timer_start( &p_conn->timer, timeout ) != CL_SUCCESS )\r
-       {\r
-               __deref_conn( p_conn );\r
-       }\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-void\r
-__do_mra_callback(\r
-       IN                              al_conn_t* const                        p_conn,\r
-       IN              const   mad_cm_mra_t* const                     p_mra )\r
-{\r
-       ib_cm_mra_rec_t mra_rec;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       CL_ASSERT( p_conn->h_qp );\r
-\r
-       /* Format the MRA callback record. */\r
-       cl_memclr( &mra_rec, sizeof( ib_cm_mra_rec_t ) );\r
-\r
-       mra_rec.h_qp = p_conn->h_qp;\r
-       mra_rec.qp_context = p_conn->h_qp->obj.context;\r
-       mra_rec.p_mra_pdata = p_mra->pdata;\r
-\r
-       /*\r
-        * Call the user back. Note that users will get a callback only\r
-        * for the first MRA received in response to a REQ, REP, or LAP.\r
-        */\r
-       p_conn->pfn_cm_mra_cb( &mra_rec );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-void\r
-__process_cm_mra(\r
-       IN                              cl_async_proc_item_t            *p_item )\r
-{\r
-       cm_port_agent_t *p_port_cm;\r
-       mad_cm_mra_t    *p_mra;\r
-       cm_async_mad_t  *p_async_mad;\r
-       cl_map_item_t   *p_map_item;\r
-       al_conn_t               *p_conn;\r
-       boolean_t               do_callback = TRUE;\r
-       uint64_t                key;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_async_mad = PARENT_STRUCT( p_item, cm_async_mad_t, item );\r
-       p_port_cm = p_async_mad->p_port_cm;\r
-       p_mra = (mad_cm_mra_t*)p_async_mad->p_mad->p_mad_buf;\r
-\r
-       cl_spinlock_acquire( &gp_cm->obj.lock );\r
-       if( conn_mra_get_msg_mraed( p_mra ) == 2 )\r
-       {\r
-               key = ((uint64_t)p_mra->remote_comm_id << 32) |\r
-                       ((uint64_t)p_mra->local_comm_id );\r
-\r
-               p_map_item = cl_qmap_get( &gp_cm->conn_map, key );\r
-               if( p_map_item == cl_qmap_end( &gp_cm->conn_map ) )\r
-               {\r
-                       cl_spinlock_release( &gp_cm->obj.lock );\r
-                       ib_put_mad( p_async_mad->p_mad );\r
-                       cl_free( p_async_mad );\r
-\r
-                       AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                               ("MRA received for LAP that could not be matched.\n") );\r
-                       return;\r
-               }\r
-       }\r
-       else\r
-       {\r
-               p_map_item = (cl_map_item_t*)cl_qlist_find_from_head(\r
-                       &gp_cm->pending_list, __mra_match, p_mra );\r
-               if( p_map_item ==\r
-                       (cl_map_item_t*)cl_qlist_end( &gp_cm->pending_list ) )\r
-               {\r
-                       AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                               ("MRA received that could not be matched.\n") );\r
-\r
-                       cl_spinlock_release( &gp_cm->obj.lock );\r
-                       ib_put_mad( p_async_mad->p_mad );\r
-                       cl_free( p_async_mad );\r
-                       return;\r
-               }\r
-       }\r
-\r
-       p_conn = PARENT_STRUCT( p_map_item, al_conn_t, map_item );\r
-\r
-       __ref_conn( p_conn );\r
-       cl_spinlock_release( &gp_cm->obj.lock );\r
-\r
-       cm_res_acquire( p_conn );\r
-\r
-       switch( p_conn->state )\r
-       {\r
-       case CM_CONN_REQ_MRA_RCVD:\r
-               do_callback = FALSE;\r
-       case CM_CONN_REQ_SENT:\r
-               /* MRA is not for the REQ. Drop it. */\r
-               if( conn_mra_get_msg_mraed( p_mra ) != 0 )\r
-               {\r
-                       do_callback = FALSE;\r
-                       break;\r
-               }\r
-               /* Store the remote communication ID. */\r
-               p_conn->remote_comm_id = p_mra->local_comm_id;\r
-               __start_mra_timer( p_conn, p_mra );\r
-               p_conn->state = CM_CONN_REQ_MRA_RCVD;\r
-               break;\r
-\r
-       case CM_CONN_REP_MRA_RCVD:\r
-               do_callback = FALSE;\r
-       case CM_CONN_REP_SENT:\r
-               /* MRA is not for the REP. Drop it. */\r
-               if( conn_mra_get_msg_mraed( p_mra ) != 1 )\r
-               {\r
-                       do_callback = FALSE;\r
-                       break;\r
-               }\r
-               __start_mra_timer( p_conn, p_mra );\r
-               p_conn->state = CM_CONN_REP_MRA_RCVD;\r
-               break;\r
-\r
-       case CM_CONN_LAP_MRA_RCVD:\r
-               do_callback = FALSE;\r
-       case CM_CONN_LAP_SENT:\r
-               /* MRA is not for the LAP. Drop it. */\r
-               if( conn_mra_get_msg_mraed( p_mra ) != 2 )\r
-               {\r
-                       do_callback = FALSE;\r
-                       break;\r
-               }\r
-               __start_mra_timer( p_conn, p_mra );\r
-               p_conn->state = CM_CONN_LAP_MRA_RCVD;\r
-               break;\r
-\r
-       default:\r
-               AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_CM,\r
-                       ("MRA received in invalid state.\n") );\r
-               do_callback = FALSE;\r
-               break;\r
-       }\r
-\r
-       cm_res_release( p_conn );\r
-       if( do_callback )\r
-               __do_mra_callback( p_conn, p_mra );\r
-       __deref_conn( p_conn );\r
-\r
-       ib_put_mad( p_async_mad->p_mad );\r
-       cl_free( p_async_mad );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-void\r
-__do_rej_callback(\r
-       IN                              al_conn_t* const                        p_conn,\r
-       IN              const   mad_cm_rej_t* const                     p_rej )\r
-{\r
-       ib_cm_rej_rec_t rej_rec;\r
-\r
-       /* Format the REJ callback record. */\r
-       cl_memclr( &rej_rec, sizeof( ib_cm_rej_rec_t ) );\r
-\r
-       CL_ASSERT( p_conn->h_qp );\r
-\r
-       rej_rec.h_qp = p_conn->h_qp;\r
-       rej_rec.qp_context = p_conn->h_qp->obj.context;\r
-\r
-       rej_rec.p_rej_pdata = p_rej->pdata;\r
-       rej_rec.p_ari = p_rej->ari;\r
-       rej_rec.ari_length = conn_rej_get_ari_len( p_rej );\r
-       rej_rec.rej_status = p_rej->reason;\r
-\r
-       /*\r
-        * Unbind the QP from the connection object.  This allows the QP to\r
-        * be immediately reused in another connection request.\r
-        */\r
-       __cm_conn_unbind( p_conn, 0 );\r
-\r
-       /* Call the user back. */\r
-       p_conn->pfn_cm_rej_cb( &rej_rec );\r
-}\r
-\r
-\r
-/*\r
- * Matches a connection by CA GUID and communication ID.\r
- */\r
-cl_status_t\r
-__rej_match(\r
-       IN              const   cl_list_item_t* const           p_list_item,\r
-       IN                              void                                            *context )\r
-{\r
-       al_conn_t                                       *p_conn;\r
-       mad_cm_rej_t                            *p_rej;\r
-       const ib_net64_t UNALIGNED      *p_ca_guid;\r
-       uint8_t                                         ari_len;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_conn = PARENT_STRUCT( p_list_item, al_conn_t, map_item );\r
-       p_rej = (mad_cm_rej_t*)context;\r
-\r
-       /* Either one of the communication IDs must be set. */\r
-       CL_ASSERT( p_rej->remote_comm_id || p_rej->local_comm_id );\r
-\r
-       /* REJ remote comm ID can be zero if rejecting due to REP timeout. */\r
-       if( p_rej->remote_comm_id &&\r
-               p_conn->local_comm_id != p_rej->remote_comm_id )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("Local comm ID mismatch.\n") );\r
-               return CL_NOT_FOUND;\r
-       }\r
-\r
-       /* Only match on remote comm ID if set. */\r
-       if( p_conn->remote_comm_id &&\r
-               p_conn->remote_comm_id != p_rej->local_comm_id )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("Remote comm ID mismatch.\n") );\r
-               return CL_NOT_FOUND;\r
-       }\r
-\r
-       /* If rejection is due to a REP timeout, compare the CA GUID. */\r
-       p_ca_guid = (const net64_t*)p_rej->ari;\r
-       ari_len = conn_rej_get_ari_len( p_rej );\r
-       if( p_rej->reason == IB_REJ_TIMEOUT &&\r
-               ari_len == sizeof(ib_net64_t) )\r
-       {\r
-               /* Only check if a connection req is started*/\r
-               if( ( p_conn->p_req_info->p_ca_attr ) &&\r
-                       ( p_conn->p_req_info->p_ca_attr->ca_guid != *p_ca_guid ) )\r
-               {\r
-                       AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                               ("Local CA GUID mismatch.\n") );\r
-                       return CL_NOT_FOUND;\r
-               }\r
-       }\r
-\r
-       /* We reached here with a comm id match which is good enough for me */\r
-\r
-       __ref_conn( p_conn );\r
-       AL_EXIT( AL_DBG_CM );\r
-       return CL_SUCCESS;\r
-}\r
-\r
-\r
-void\r
-__process_cm_rej(\r
-       IN                              cl_async_proc_item_t            *p_item )\r
-{\r
-       cm_port_agent_t *p_port_cm;\r
-       mad_cm_rej_t    *p_rej;\r
-       cm_async_mad_t  *p_async_mad;\r
-       cl_map_item_t   *p_map_item;\r
-       al_conn_t               *p_conn;\r
-       uint64_t                key;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_async_mad = PARENT_STRUCT( p_item, cm_async_mad_t, item );\r
-       p_port_cm = p_async_mad->p_port_cm;\r
-       p_rej = (mad_cm_rej_t*)p_async_mad->p_mad->p_mad_buf;\r
-\r
-       /* Check the pending list by the remote CA GUID and connection ID. */\r
-       cl_spinlock_acquire( &gp_cm->obj.lock );\r
-       p_map_item = (cl_map_item_t*)cl_qlist_find_from_head( &gp_cm->pending_list,\r
-               __rej_match, p_rej );\r
-       if( p_map_item == (cl_map_item_t*)cl_qlist_end( &gp_cm->pending_list ) )\r
-       {\r
-               /* Not in the pending list, check the connection map. */\r
-               key = ((uint64_t)p_rej->remote_comm_id << 32) |\r
-                       ((uint64_t)p_rej->local_comm_id );\r
-\r
-               p_map_item = cl_qmap_get( &gp_cm->conn_map, key );\r
-               if( p_map_item == cl_qmap_end( &gp_cm->conn_map ) )\r
-               {\r
-                       cl_spinlock_release( &gp_cm->obj.lock );\r
-                       ib_put_mad( p_async_mad->p_mad );\r
-                       cl_free( p_async_mad );\r
-\r
-                       AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                               ("REJ received that could not be matched.\n") );\r
-                       return;\r
-               }\r
-               p_conn = PARENT_STRUCT( p_map_item, al_conn_t, map_item );\r
-               __ref_conn( p_conn );\r
-       }\r
-       else\r
-       {\r
-               p_conn = PARENT_STRUCT( p_map_item, al_conn_t, map_item );\r
-       }\r
-\r
-       cl_spinlock_release( &gp_cm->obj.lock );\r
-       cm_res_acquire( p_conn );\r
-\r
-       switch( p_conn->state )\r
-       {\r
-       case CM_CONN_REQ_SENT:\r
-               /*\r
-                * Ignore rejects with the status set to IB_REJ_INVALID_SID.  We will\r
-                * continue to retry (up to max_cm_retries) to connect to the remote\r
-                * side.  This is required to support peer-to-peer connections and\r
-                * clients that try to connect before the server comes up.\r
-                */\r
-               if( (p_rej->reason == IB_REJ_INVALID_SID) &&\r
-                       p_conn->max_cm_retries )\r
-               {\r
-                       p_conn->max_cm_retries--;\r
-                       /* Deref the connection to match the reference taken when matching. */\r
-                       cm_res_release( p_conn );\r
-                       __deref_conn( p_conn );\r
-                       ib_put_mad( p_async_mad->p_mad );\r
-                       cl_free( p_async_mad );\r
-                       AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                               ("Request rejected (invalid SID) - retrying.\n") );\r
-                       return;\r
-               }\r
-\r
-               /* Fall through */\r
-       case CM_CONN_REP_SENT:\r
-               /* Cancel any outstanding MAD. */\r
-               ib_cancel_mad( p_conn->h_mad_svc, p_conn->p_send_mad );\r
-               p_conn->p_send_mad = NULL;\r
-\r
-               /* Fall through */\r
-\r
-       case CM_CONN_REQ_RCVD:\r
-       case CM_CONN_REP_RCVD:\r
-       case CM_CONN_REQ_MRA_RCVD:\r
-       case CM_CONN_REQ_MRA_SENT:\r
-       case CM_CONN_REP_MRA_RCVD:\r
-       case CM_CONN_REP_MRA_SENT:\r
-       case CM_CONN_ESTABLISHED:\r
-               /* Notify the user only for a valid CEP. */\r
-               /* TODO: Can this IF go away? */\r
-               if( p_conn->h_qp )\r
-                       __do_rej_callback( p_conn, p_rej );\r
-\r
-               /* Abort connection establishment. No transition to timewait. */\r
-               __conn_abort( p_conn );\r
-\r
-               cm_res_release( p_conn );\r
-               break;\r
-\r
-       default:\r
-               /* Ignore the REJ. */\r
-               cm_res_release( p_conn );\r
-\r
-               /* Deref the connection to match the reference taken when matching. */\r
-               __deref_conn( p_conn );\r
-               ib_put_mad( p_async_mad->p_mad );\r
-               cl_free( p_async_mad );\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("REJ received in invalid state.\n") );\r
-               return;\r
-       }\r
-\r
-       /* Deref the connection to match the reference taken when matching. */\r
-       __deref_conn( p_conn );\r
-       ib_put_mad( p_async_mad->p_mad );\r
-       cl_free( p_async_mad );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-/*\r
- * Function invoked to send a REJ.\r
- */\r
-void\r
-__conn_reject(\r
-       IN                              al_conn_t* const                        p_conn,\r
-       IN              const   ib_rej_status_t                         reason,\r
-       IN              const   ib_ari_t* const                         p_ari OPTIONAL,\r
-       IN              const   uint8_t                                         ari_length,\r
-       IN              const   ib_rej_pdata_t* const           p_rej_pdata OPTIONAL )\r
-{\r
-       cm_port_agent_t         *p_port_cm;\r
-       ib_api_status_t         status;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-       UNUSED_PARAM( p_rej_pdata );\r
-\r
-       /*\r
-        * Format the reject information.\r
-        */\r
-       p_conn->mads.rej.hdr.attr_id = CM_REJ_ATTR_ID;\r
-       p_conn->mads.rej.remote_comm_id = p_conn->remote_comm_id;\r
-       p_conn->mads.rej.local_comm_id = p_conn->local_comm_id;\r
-       switch( p_conn->state )\r
-       {\r
-       case CM_CONN_REQ_RCVD:\r
-               conn_rej_set_msg_rejected( 0, &p_conn->mads.rej );\r
-               break;\r
-\r
-       case CM_CONN_REP_RCVD:\r
-               conn_rej_set_msg_rejected( 1, &p_conn->mads.rej );\r
-               break;\r
-\r
-       default:\r
-               conn_rej_set_msg_rejected( 2, &p_conn->mads.rej );\r
-               break;\r
-       }\r
-\r
-       p_conn->mads.rej.reason = reason;\r
-\r
-       /* Copy ARI data, if any. */\r
-       if( reason == IB_REJ_TIMEOUT )\r
-       {\r
-               /* ARI contains CA GUID. */\r
-               /* Copy the local CA GUID into the ARI. */\r
-               conn_rej_set_ari( (uint8_t*)&p_conn->p_req_info->p_ca_attr->ca_guid,\r
-                       sizeof(ib_net64_t), &p_conn->mads.rej );\r
-       }\r
-       else if( p_ari )\r
-       {\r
-               conn_rej_set_ari( p_ari->data, ari_length, &p_conn->mads.rej );\r
-       }\r
-       else\r
-       {\r
-               conn_rej_set_ari( NULL, 0, &p_conn->mads.rej );\r
-       }\r
-\r
-       /* Copy private data, if any. */\r
-       conn_rej_set_pdata( NULL, 0, &p_conn->mads.rej );\r
-\r
-       conn_rej_clr_rsvd_fields( &p_conn->mads.rej );\r
-\r
-       status = __get_port_attr( &p_conn->path[0].sgid, p_conn->path[0].slid,\r
-               &p_port_cm, NULL );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("__get_port_attr returned %s\n", ib_get_err_str(status)) );\r
-               return;\r
-       }\r
-\r
-       /* Cancel any outstanding sends. */\r
-       if( p_conn->p_send_mad )\r
-       {\r
-               ib_cancel_mad( p_conn->h_mad_svc, p_conn->p_send_mad );\r
-               p_conn->p_send_mad = NULL;\r
-       }\r
-\r
-       __cm_send( p_port_cm, p_conn );\r
-       __conn_abort( p_conn );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-/*\r
- * Matches a connection given a REP.\r
- */\r
-cl_status_t\r
-__rep_match(\r
-       IN              const   cl_list_item_t* const           p_list_item,\r
-       IN                              void                                            *context )\r
-{\r
-       al_conn_t               *p_conn;\r
-       mad_cm_rep_t    *p_rep;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_conn = PARENT_STRUCT( p_list_item, al_conn_t, map_item );\r
-       p_rep = (mad_cm_rep_t*)context;\r
-\r
-       AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_CM,\r
-               ("p_conn:: local_comm_id (x%x) remote_comm_id (x%x)\n"\r
-               "p_rep:: local_comm_id (x%x) remote_comm_id (x%x)\n",\r
-               p_conn->local_comm_id,\r
-               p_conn->remote_comm_id,\r
-               p_rep->local_comm_id,\r
-               p_rep->remote_comm_id ) );\r
-\r
-       if( p_conn->local_comm_id != p_rep->remote_comm_id )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("Local comm ID mismatch.\n") );\r
-               return CL_NOT_FOUND;\r
-       }\r
-\r
-       __ref_conn( p_conn );\r
-       AL_EXIT( AL_DBG_CM );\r
-       return CL_SUCCESS;\r
-}\r
-\r
-\r
-\r
-void\r
-__format_rep_rec(\r
-       IN              const   mad_cm_rep_t*           const   p_rep,\r
-       IN              const   al_conn_t*                      const   p_conn,\r
-               OUT                     ib_cm_rep_rec_t*        const   p_rep_rec )\r
-{\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       cl_memclr( p_rep_rec, sizeof(ib_cm_rep_rec_t) );\r
-\r
-       /* fill the rec callback data */\r
-       p_rep_rec->p_rep_pdata = p_rep->pdata;\r
-       p_rep_rec->qp_type = p_conn->qp_type;\r
-\r
-       p_rep_rec->h_cm_rep = (ib_cm_handle_t)p_conn;\r
-       p_rep_rec->qp_context = p_conn->h_qp->obj.context;\r
-       p_rep_rec->resp_res = p_rep->resp_resources;\r
-       p_rep_rec->flow_ctrl = conn_rep_get_e2e_flow_ctl( p_rep );\r
-       p_rep_rec->apr_status = conn_rep_get_failover( p_rep );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-void\r
-__conn_save_wire_rep(\r
-       IN              const   mad_cm_rep_t*           const   p_rep,\r
-               OUT                     al_conn_t*                      const   p_conn )\r
-{\r
-       struct _qp_rtr          *p_rtr;\r
-       struct _qp_rts          *p_rts;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       /* The send should have been cancelled during MRA processing. */\r
-       p_conn->state = CM_CONN_REP_RCVD;\r
-\r
-       /* Store pertinent information in the connection. */\r
-       p_conn->remote_comm_id = p_rep->local_comm_id;\r
-       p_conn->remote_ca_guid = p_rep->remote_comm_id;\r
-\r
-       p_conn->remote_qpn = conn_rep_get_lcl_qpn( p_rep );\r
-\r
-       /*\r
-        * Store the target ack delay.  This is used to calculate the\r
-        * ack timeouts when setting up address vectors for alternate paths.\r
-        */\r
-       p_conn->target_ack_delay = conn_rep_get_target_ack_delay( p_rep );\r
-\r
-       /* Setup the QP modify structures for the RTR and RTS transitions */\r
-       p_rtr = &p_conn->p_req_info->qp_mod_rtr.state.rtr;\r
-       p_rts = &p_conn->p_req_info->qp_mod_rts.state.rts;\r
-\r
-       /* Save RTR info */\r
-       p_rtr->dest_qp = conn_rep_get_lcl_qpn( p_rep );\r
-\r
-       p_rtr->primary_av.conn.rnr_retry_cnt = conn_rep_get_rnr_retry_cnt( p_rep );\r
-\r
-       p_rtr->primary_av.conn.local_ack_timeout = cm_local_ack_timeout(\r
-               ib_path_rec_pkt_life( &p_conn->path[0] ), p_conn->target_ack_delay );\r
-       if( p_conn->path[1].slid )\r
-       {\r
-               p_rtr->alternate_av.conn.rnr_retry_cnt =\r
-                       conn_rep_get_rnr_retry_cnt( p_rep );\r
-               p_rtr->alternate_av.conn.local_ack_timeout = cm_local_ack_timeout(\r
-                       ib_path_rec_pkt_life( &p_conn->path[1] ),\r
-                       p_conn->target_ack_delay );\r
-       }\r
-\r
-       /* Saved in a REQ and/or passed back to user in rep_rec callback\r
-       p_rtr->resp_res;\r
-       p_rtr->qkey;\r
-       p_rtr->sq_depth;\r
-       p_rtr->rq_depth;\r
-       p_rtr->rq_psn;\r
-       */\r
-\r
-       /* Save RTS info */\r
-       p_rts->rnr_retry_cnt = conn_rep_get_rnr_retry_cnt( p_rep );\r
-\r
-       /* Responder resources and initiator depth are only for RC QPs. */\r
-       if( p_conn->p_req_info->xport_type == IB_QPT_RELIABLE_CONN )\r
-       {\r
-               p_rtr->resp_res = p_rep->initiator_depth;\r
-               p_rts->init_depth = p_rep->resp_resources;\r
-       }\r
-\r
-       /* Set the APM state. */\r
-       if( conn_rep_get_failover( p_rep ) == IB_AP_SUCCESS )\r
-       {\r
-               p_rts->opts |= IB_MOD_QP_APM_STATE;\r
-               p_rts->apm_state = IB_APM_REARM;\r
-       }\r
-\r
-       p_rts->sq_psn = conn_rep_get_starting_psn( p_rep );\r
-\r
-       /* Saved in REQ and/or passed back in rep_rec callback\r
-       p_rts->retry_cnt;\r
-       p_rts->rnr_nak_timeout;\r
-       p_rts->local_ack_timeout;\r
-       p_rts->access_ctrl;\r
-       p_rts->sq_depth;\r
-       p_rts->rq_depth;\r
-       p_rts->primary_port;\r
-       p_rts->opts;\r
-       p_rts->qkey = p_rep->local_qkey;\r
-       */\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-void\r
-__process_cm_rep(\r
-       IN                              cl_async_proc_item_t            *p_item )\r
-{\r
-       mad_cm_rep_t            *p_rep;\r
-       cm_async_mad_t          *p_async_mad;\r
-       cl_map_item_t           *p_map_item;\r
-       al_conn_t                       *p_conn;\r
-       ib_cm_rep_rec_t         rep_rec;\r
-       uint64_t                        key;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_async_mad = PARENT_STRUCT( p_item, cm_async_mad_t, item );\r
-       p_rep = (mad_cm_rep_t*)p_async_mad->p_mad->p_mad_buf;\r
-\r
-       AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_CM, ("REP: comm_id (x%x) received\n",\r
-               p_rep->local_comm_id ) );\r
-\r
-       /* Check the pending list by the local connection ID. */\r
-       cl_spinlock_acquire( &gp_cm->obj.lock );\r
-       p_map_item = (cl_map_item_t*)cl_qlist_find_from_head( &gp_cm->pending_list,\r
-               __rep_match, p_rep );\r
-       if( p_map_item == (cl_map_item_t*)cl_qlist_end( &gp_cm->pending_list ) )\r
-       {\r
-               /* Not in the pending list, check the connection map. */\r
-               key = ((uint64_t)p_rep->remote_comm_id << 32) |\r
-                       ((uint64_t)p_rep->local_comm_id );\r
-\r
-               p_map_item = cl_qmap_get( &gp_cm->conn_map, key );\r
-               if( p_map_item == cl_qmap_end( &gp_cm->conn_map ) )\r
-               {\r
-                       cl_spinlock_release( &gp_cm->obj.lock );\r
-                       ib_put_mad( p_async_mad->p_mad );\r
-                       cl_free( p_async_mad );\r
-\r
-                       AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                               ("REP received that could not be matched.\n") );\r
-                       return;\r
-               }\r
-               p_conn = PARENT_STRUCT( p_map_item, al_conn_t, map_item );\r
-               __ref_conn( p_conn );\r
-       }\r
-       else\r
-       {\r
-               p_conn = PARENT_STRUCT( p_map_item, al_conn_t, map_item );\r
-       }\r
-\r
-       cl_spinlock_release( &gp_cm->obj.lock );\r
-       cm_res_acquire( p_conn );\r
-\r
-       switch( p_conn->state )\r
-       {\r
-       case CM_CONN_REQ_SENT:\r
-               /* Cancel any outstanding send. */\r
-               ib_cancel_mad( p_conn->h_mad_svc, p_conn->p_send_mad );\r
-               p_conn->p_send_mad = NULL;\r
-\r
-               /* Fall through. */\r
-       case CM_CONN_REQ_MRA_RCVD:\r
-               if( p_conn->state == CM_CONN_REQ_MRA_RCVD )\r
-               {\r
-                       /* Cancel the MRA timer and release its reference. */\r
-                       cl_timer_stop( &p_conn->timer );\r
-                       __deref_conn( p_conn );\r
-               }\r
-\r
-               __conn_save_wire_rep( p_rep, p_conn );\r
-               __format_rep_rec( p_rep, p_conn, &rep_rec );\r
-\r
-               cm_res_release( p_conn );\r
-               /* Reference the connection until the user calls REJ or RTU. */\r
-               __ref_conn( p_conn );\r
-\r
-               /* Notify the user of the reply. */\r
-               p_conn->p_req_info->pfn_cm_rep_cb( &rep_rec );\r
-\r
-               ib_put_mad( p_async_mad->p_mad );\r
-               break;\r
-\r
-       case CM_CONN_ESTABLISHED:\r
-               cm_res_release( p_conn );\r
-               /* Repeate the RTU. */\r
-               __repeated_mad( p_async_mad->p_port_cm, p_conn, p_async_mad->p_mad );\r
-               break;\r
-\r
-       default:\r
-               AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_CM,\r
-                       ("REP received in invalid state.\n") );\r
-               cm_res_release( p_conn );\r
-               ib_put_mad( p_async_mad->p_mad );\r
-               break;\r
-       }\r
-       /* Release the reference acquired when matching the connection. */\r
-       __deref_conn( p_conn );\r
-       cl_free( p_async_mad );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-/*\r
- * Matches a connection given an RTU.\r
- */\r
-cl_status_t\r
-__rtu_match(\r
-       IN              const   cl_list_item_t* const           p_list_item,\r
-       IN                              void                                            *context )\r
-{\r
-       al_conn_t               *p_conn;\r
-       mad_cm_rtu_t    *p_rtu;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_conn = PARENT_STRUCT( p_list_item, al_conn_t, map_item );\r
-       p_rtu = (mad_cm_rtu_t*)context;\r
-\r
-       if( p_conn->local_comm_id != p_rtu->remote_comm_id )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("Local comm ID mismatch.\n") );\r
-               return CL_NOT_FOUND;\r
-       }\r
-\r
-       if( p_conn->remote_comm_id != p_rtu->local_comm_id )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("Remote comm ID mismatch.\n") );\r
-               return CL_NOT_FOUND;\r
-       }\r
-\r
-       __ref_conn( p_conn );\r
-       AL_EXIT( AL_DBG_CM );\r
-       return CL_SUCCESS;\r
-}\r
-\r
-void\r
-__format_rtu_rec(\r
-       IN      const   mad_cm_rtu_t*           const   p_rtu,\r
-       IN      const   al_conn_t*                      const   p_conn,\r
-               OUT             ib_cm_rtu_rec_t*        const   p_rtu_rec )\r
-{\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       cl_memclr( p_rtu_rec, sizeof(ib_cm_rtu_rec_t) );\r
-\r
-       p_rtu_rec->p_rtu_pdata = p_rtu->pdata;\r
-       p_rtu_rec->qp_type = p_conn->qp_type;\r
-       p_rtu_rec->h_qp = p_conn->h_qp;\r
-       p_rtu_rec->qp_context = p_conn->h_qp->obj.context;\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-void\r
-__process_cm_rtu(\r
-       IN                              cl_async_proc_item_t            *p_item )\r
-{\r
-       mad_cm_rtu_t                    *p_rtu;\r
-       cm_async_mad_t                  *p_async_mad;\r
-       cl_list_item_t                  *p_list_item;\r
-       al_conn_t                               *p_conn;\r
-       ib_pfn_cm_rtu_cb_t              pfn_rtu;\r
-       ib_cm_rtu_rec_t                 rtu_rec;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_async_mad = PARENT_STRUCT( p_item, cm_async_mad_t, item );\r
-       p_rtu = (mad_cm_rtu_t*)p_async_mad->p_mad->p_mad_buf;\r
-\r
-       AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_CM, ("RTU: comm_id (x%x) received\n",\r
-               p_rtu->local_comm_id ) );\r
-\r
-       /* Find the connection by local connection ID. */\r
-       cl_spinlock_acquire( &gp_cm->obj.lock );\r
-       p_list_item = cl_qlist_find_from_head( &gp_cm->pending_list,\r
-               __rtu_match, p_rtu );\r
-       cl_spinlock_release( &gp_cm->obj.lock );\r
-       if( p_list_item == cl_qlist_end( &gp_cm->pending_list ) )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("RTU received that could not be matched.\n") );\r
-               ib_put_mad( p_async_mad->p_mad );\r
-               cl_free( p_async_mad );\r
-               return;\r
-       }\r
-\r
-       p_conn = PARENT_STRUCT( p_list_item, al_conn_t, map_item );\r
-       cm_res_acquire( p_conn );\r
-\r
-       switch( p_conn->state )\r
-       {\r
-       case CM_CONN_REP_SENT:\r
-               /* Cancel any outstanding send. */\r
-               ib_cancel_mad( p_conn->h_mad_svc, p_conn->p_send_mad );\r
-               p_conn->p_send_mad = NULL;\r
-\r
-               /* Fall through. */\r
-       case CM_CONN_REP_MRA_RCVD:\r
-               if( p_conn->state == CM_CONN_REP_MRA_RCVD )\r
-               {\r
-                       /* Cancel the MRA timer and release its reference. */\r
-                       cl_timer_stop( &p_conn->timer );\r
-                       __deref_conn( p_conn );\r
-               }\r
-\r
-               /* The send should have been cancelled during MRA processing. */\r
-               p_conn->state = CM_CONN_ESTABLISHED;\r
-\r
-               /* Store the callback pointers. */\r
-               pfn_rtu = p_conn->p_req_info->pfn_cm_rtu_cb;\r
-\r
-               /* Move the connection from the pending list to the connection map. */\r
-               __migrate_conn_to_map( p_conn );\r
-\r
-               /* Release the request info. */\r
-               cm_res_release( p_conn );\r
-\r
-               /* callback user */\r
-               __format_rtu_rec( p_rtu, p_conn, &rtu_rec );\r
-               pfn_rtu( &rtu_rec );\r
-\r
-               break;\r
-\r
-       default:\r
-               AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_CM,\r
-                       ("RTU received in invalid state.\n") );\r
-               cm_res_release( p_conn );\r
-               break;\r
-       }\r
-\r
-       /* Release the reference acquired when matching the connection. */\r
-       __deref_conn( p_conn );\r
-       ib_put_mad( p_async_mad->p_mad );\r
-       cl_free( p_async_mad );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-/*\r
- * Matches a connection given a DREQ.\r
- */\r
-cl_status_t\r
-__dreq_match(\r
-       IN              const   cl_list_item_t* const           p_list_item,\r
-       IN                              void                                            *context )\r
-{\r
-       al_conn_t               *p_conn;\r
-       mad_cm_dreq_t   *p_dreq;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_conn = PARENT_STRUCT( p_list_item, al_conn_t, map_item );\r
-       p_dreq = (mad_cm_dreq_t*)context;\r
-\r
-       if( p_conn->local_comm_id != p_dreq->remote_comm_id )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("Local comm ID mismatch.\n") );\r
-               return CL_NOT_FOUND;\r
-       }\r
-\r
-       if( p_conn->remote_comm_id != p_dreq->local_comm_id )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("Remote comm ID mismatch.\n") );\r
-               return CL_NOT_FOUND;\r
-       }\r
-\r
-       if( p_conn->local_qpn != conn_dreq_get_remote_qpn( p_dreq ) )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("local QPN mismatch.\n") );\r
-               return CL_NOT_FOUND;\r
-       }\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return CL_SUCCESS;\r
-}\r
-\r
-void\r
-__format_dreq_rec(\r
-       IN      const   mad_cm_dreq_t*          const   p_dreq,\r
-       IN      const   al_conn_t*                      const   p_conn,\r
-               OUT             ib_cm_dreq_rec_t*       const   p_dreq_rec )\r
-{\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       cl_memclr( p_dreq_rec, sizeof(ib_cm_dreq_rec_t) );\r
-\r
-       p_dreq_rec->h_cm_dreq = (ib_cm_handle_t)p_conn;\r
-       p_dreq_rec->p_dreq_pdata = p_dreq->pdata;\r
-\r
-       p_dreq_rec->qp_type = p_conn->qp_type;\r
-       p_dreq_rec->qp_context = p_conn->h_qp->obj.context;\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-\r
-void\r
-__process_cm_dreq(\r
-       IN                              cl_async_proc_item_t            *p_item )\r
-{\r
-       mad_cm_dreq_t           *p_dreq;\r
-       cm_async_mad_t          *p_async_mad;\r
-       cl_map_item_t           *p_map_item;\r
-       al_conn_t                       *p_conn;\r
-       uint64_t                        key;\r
-       ib_cm_dreq_rec_t        dreq_rec;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_async_mad = PARENT_STRUCT( p_item, cm_async_mad_t, item );\r
-       p_dreq = (mad_cm_dreq_t*)p_async_mad->p_mad->p_mad_buf;\r
-\r
-       /* Find the connection by connection IDs. */\r
-       key = ( (uint64_t)p_dreq->remote_comm_id ) << 32 |\r
-               ( (uint64_t)p_dreq->local_comm_id );\r
-       cl_spinlock_acquire( &gp_cm->obj.lock );\r
-       p_map_item = cl_qmap_get( &gp_cm->conn_map, key );\r
-       if( p_map_item == cl_qmap_end( &gp_cm->conn_map ) )\r
-       {\r
-               /* Look in the timewait list in order to repeat the final DREP. */\r
-               p_map_item = (cl_map_item_t*)cl_qlist_find_from_head(\r
-                       &gp_cm->time_wait_list, __dreq_match, p_dreq );\r
-               if( p_map_item ==\r
-                       (cl_map_item_t*)cl_qlist_end( &gp_cm->time_wait_list ) )\r
-               {\r
-                       cl_spinlock_release( &gp_cm->obj.lock );\r
-                       AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                               ("DREQ received that could not be matched.\n") );\r
-                       ib_put_mad( p_async_mad->p_mad );\r
-                       cl_free( p_async_mad );\r
-                       return;\r
-               }\r
-       }\r
-\r
-       p_conn = PARENT_STRUCT( p_map_item, al_conn_t, map_item );\r
-\r
-       /*\r
-        * Reference the connection to sync with a destroy QP and prevent the\r
-        * connection object from being destroyed while in a callback.\r
-        */\r
-       __ref_conn( p_conn );\r
-\r
-       cl_spinlock_release( &gp_cm->obj.lock );\r
-\r
-       cm_res_acquire( p_conn );\r
-       /* Do the additional check as per spec. */\r
-       if( p_conn->local_qpn != conn_dreq_get_remote_qpn( p_dreq ) )\r
-       {\r
-               cm_res_release( p_conn );\r
-\r
-               __deref_conn( p_conn );\r
-               ib_put_mad( p_async_mad->p_mad );\r
-               cl_free( p_async_mad );\r
-               AL_EXIT( AL_DBG_CM );\r
-               return;\r
-       }\r
-\r
-       switch( p_conn->state )\r
-       {\r
-       case CM_CONN_REP_SENT:\r
-       case CM_CONN_DREQ_SENT:\r
-               /* Cancel the outstanding MAD. */\r
-               ib_cancel_mad( p_conn->h_mad_svc, p_conn->p_send_mad );\r
-               p_conn->p_send_mad = NULL;\r
-\r
-               /* Fall through and process as DREQ received case. */\r
-       case CM_CONN_ESTABLISHED:\r
-               /*\r
-                * The user must call ib_cm_drep.  Continue to hold the initial\r
-                * reference on p_conn until the user makes the call (or we give\r
-                * up waiting on them).\r
-                */\r
-               p_conn->state = CM_CONN_DREQ_RCVD;\r
-\r
-               __format_dreq_rec( p_dreq, p_conn, &dreq_rec );\r
-\r
-               cm_res_release( p_conn );\r
-               p_conn->pfn_cm_dreq_cb( &dreq_rec );\r
-               ib_put_mad( p_async_mad->p_mad );\r
-               break;\r
-\r
-       case CM_CONN_DREP_SENT:\r
-       case CM_CONN_TIMEWAIT:\r
-               cm_res_release( p_conn );\r
-               /* Repeat the DREP. */\r
-               __repeated_mad( p_async_mad->p_port_cm, p_conn, p_async_mad->p_mad );\r
-               break;\r
-\r
-       default:\r
-               AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_CM,\r
-                       ("DREQ received in invalid state.\n") );\r
-               cm_res_release( p_conn );\r
-               ib_put_mad( p_async_mad->p_mad );\r
-               break;\r
-       }\r
-\r
-       /* Release the reference taken above. */\r
-       __deref_conn( p_conn );\r
-       cl_free( p_async_mad );\r
-}\r
-\r
-\r
-\r
-void\r
-__format_drep_rec(\r
-       IN              const   mad_cm_drep_t*          const   p_drep,\r
-       IN              const   al_conn_t*                      const   p_conn,\r
-               OUT                     ib_cm_drep_rec_t*       const   p_drep_rec )\r
-{\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       cl_memclr( p_drep_rec, sizeof(ib_cm_drep_rec_t) );\r
-\r
-       /* Copy qp context before the connection is released */\r
-       p_drep_rec->cm_status = IB_SUCCESS;\r
-       p_drep_rec->p_drep_pdata = p_drep->pdata;\r
-       p_drep_rec->qp_type = p_conn->qp_type;\r
-       p_drep_rec->h_qp = p_conn->h_qp;\r
-       p_drep_rec->qp_context = p_conn->h_qp->obj.context;\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-void\r
-__process_cm_drep(\r
-       IN                              cl_async_proc_item_t            *p_item )\r
-{\r
-       mad_cm_drep_t           *p_drep;\r
-       cm_async_mad_t          *p_async_mad;\r
-       cl_map_item_t           *p_map_item;\r
-       uint64_t                        key;\r
-       al_conn_t                       *p_conn;\r
-       ib_cm_drep_rec_t        drep_rec;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_async_mad = PARENT_STRUCT( p_item, cm_async_mad_t, item );\r
-       p_drep = (mad_cm_drep_t*)p_async_mad->p_mad->p_mad_buf;\r
-\r
-       /* Find the connection by local connection ID. */\r
-       cl_spinlock_acquire( &gp_cm->obj.lock );\r
-       key = ( (uint64_t)p_drep->remote_comm_id << 32) |\r
-               ( (uint64_t)p_drep->local_comm_id );\r
-       p_map_item = cl_qmap_get( &gp_cm->conn_map, key );\r
-       if( p_map_item == cl_qmap_end( &gp_cm->conn_map ) )\r
-       {\r
-               cl_spinlock_release( &gp_cm->obj.lock );\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("DREP received that could not be matched.\n") );\r
-               ib_put_mad( p_async_mad->p_mad );\r
-               cl_free( p_async_mad );\r
-               return;\r
-       }\r
-\r
-       /*\r
-        * Reference the connection to sync with a destroy QP and prevent the\r
-        * connection object from being destroyed while in a callback.\r
-        */\r
-       p_conn = PARENT_STRUCT( p_map_item, al_conn_t, map_item );\r
-\r
-       __ref_conn( p_conn );\r
-       cl_spinlock_release( &gp_cm->obj.lock );\r
-\r
-       cm_res_acquire( p_conn );\r
-\r
-       switch( p_conn->state )\r
-       {\r
-       case CM_CONN_DREQ_SENT:\r
-               /* Cancel the DREQ. */\r
-               ib_cancel_mad( p_conn->h_mad_svc, p_conn->p_send_mad );\r
-               p_conn->p_send_mad = NULL;\r
-\r
-               __format_drep_rec( p_drep, p_conn, &drep_rec );\r
-\r
-               /*\r
-                * Release the connection. This puts the QP and connection object\r
-                * into the timewait state.\r
-                */\r
-               __conn_release( p_conn );\r
-               cm_res_release( p_conn );\r
-\r
-               p_conn->pfn_cm_drep_cb( &drep_rec );\r
-               break;\r
-\r
-       default:\r
-               AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_CM,\r
-                       ("DREP received in invalid state.\n") );\r
-               cm_res_release( p_conn );\r
-       }\r
-\r
-       /* Release the reference taken above. */\r
-       __deref_conn( p_conn );\r
-\r
-       ib_put_mad( p_async_mad->p_mad );\r
-       cl_free( p_async_mad );\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-void\r
-__format_lap_path_rec(\r
-       IN                              al_conn_t* const                        p_conn,\r
-       IN              const   mad_cm_lap_t* const                     p_lap,\r
-               OUT                     ib_path_rec_t* const            p_path_rec )\r
-{\r
-       const lap_path_info_t* const    p_path = &p_lap->alternate_path;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       CL_ASSERT( p_lap );\r
-       CL_ASSERT( p_path_rec );\r
-\r
-       /*\r
-        * Format a local path record. The local ack timeout specified in the\r
-        * REQ is twice the packet life plus the sender's CA ACK delay.  When\r
-        * reporting the packet life, we divide the local ack timeout by 2 to\r
-        * approach the path's packet lifetime.  Since local ack timeout is\r
-        * expressed as 4.096 * 2^x, subtracting 1 is equivalent to dividing the\r
-        * time in half.\r
-        */\r
-       ib_path_rec_init_local( p_path_rec,\r
-               &p_lap->alternate_path.local_gid,\r
-               &p_lap->alternate_path.remote_gid,\r
-               p_lap->alternate_path.local_lid,\r
-               p_lap->alternate_path.remote_lid,\r
-               1, p_conn->path[p_conn->idx_primary].pkey,\r
-               conn_lap_path_get_svc_lvl( p_path ),\r
-               IB_PATH_SELECTOR_EXACTLY,\r
-               ib_path_rec_mtu( &p_conn->path[p_conn->idx_primary] ),\r
-               IB_PATH_SELECTOR_EXACTLY,\r
-               conn_lap_path_get_pkt_rate( p_path ),\r
-               IB_PATH_SELECTOR_EXACTLY,\r
-               (uint8_t)( conn_lap_path_get_lcl_ack_timeout( p_path ) - 1 ),\r
-               0 );\r
-\r
-       p_path_rec->hop_flow_raw.val = 0;\r
-       /* Add global routing info as necessary. */\r
-       if( !conn_lap_path_get_subn_lcl( p_path ) )\r
-       {\r
-               ib_path_rec_set_hop_flow_raw( p_path_rec,\r
-                       p_lap->alternate_path.hop_limit,\r
-                       conn_lap_path_get_flow_lbl( p_path ),\r
-                       FALSE );\r
-               p_path_rec->tclass = conn_lap_path_get_tclass( p_path );\r
-       }\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-void\r
-__process_cm_lap(\r
-       IN                              cl_async_proc_item_t            *p_item )\r
-{\r
-       cm_port_agent_t *p_port_cm;\r
-       mad_cm_lap_t    *p_lap;\r
-       cm_async_mad_t  *p_async_mad;\r
-       cl_map_item_t   *p_map_item;\r
-       uint64_t                key;\r
-       al_conn_t               *p_conn;\r
-       ib_cm_lap_rec_t lap_rec;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_async_mad = PARENT_STRUCT( p_item, cm_async_mad_t, item );\r
-       p_port_cm = p_async_mad->p_port_cm;\r
-       p_lap = (mad_cm_lap_t*)p_async_mad->p_mad->p_mad_buf;\r
-\r
-       key = ((uint64_t)p_lap->remote_comm_id << 32) |\r
-               ((uint64_t)p_lap->local_comm_id );\r
-       /* Find the connection by local connection ID. */\r
-       cl_spinlock_acquire( &gp_cm->obj.lock );\r
-       p_map_item = cl_qmap_get( &gp_cm->conn_map, key );\r
-       if( p_map_item == cl_qmap_end( &gp_cm->conn_map ) )\r
-       {\r
-               cl_spinlock_release( &gp_cm->obj.lock );\r
-               ib_put_mad( p_async_mad->p_mad );\r
-               cl_free( p_async_mad );\r
-\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("LAP received that could not be matched.\n") );\r
-               return;\r
-       }\r
-\r
-       p_conn = PARENT_STRUCT( p_map_item, al_conn_t, map_item );\r
-       cl_spinlock_release( &gp_cm->obj.lock );\r
-       cm_res_acquire( p_conn );\r
-\r
-       switch( p_conn->state )\r
-       {\r
-       case CM_CONN_ESTABLISHED:\r
-               p_conn->state = CM_CONN_LAP_RCVD;\r
-               cl_memclr( &lap_rec, sizeof( ib_cm_lap_rec_t ) );\r
-               lap_rec.qp_context = p_conn->h_qp->obj.context;\r
-               lap_rec.h_cm_lap = p_conn;\r
-               /* Format the path record. */\r
-               __format_lap_path_rec( p_conn, p_lap, &lap_rec.alt_path );\r
-\r
-               lap_rec.p_lap_pdata = p_lap->pdata;\r
-\r
-               /*\r
-                * Copy the path record into the connection for use when\r
-                * sending the APR and loading the path.\r
-                */\r
-               cl_memcpy( &p_conn->new_alt_path, &lap_rec.alt_path,\r
-                       sizeof(ib_path_rec_t) );\r
-\r
-               /* Hold on to the connection reference until the user responds. */\r
-               __ref_conn( p_conn );\r
-               cm_res_release( p_conn );\r
-               p_conn->pfn_cm_lap_cb( &lap_rec );\r
-               break;\r
-\r
-       default:\r
-               AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_CM,\r
-                       ("LAP received in invalid state.\n") );\r
-               cm_res_release( p_conn );\r
-               break;\r
-       }\r
-\r
-       ib_put_mad( p_async_mad->p_mad );\r
-       cl_free( p_async_mad );\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-ib_api_status_t\r
-__cm_lap_qp(\r
-       IN                              al_conn_t* const                        p_conn )\r
-{\r
-       ib_api_status_t         status;\r
-       cm_port_agent_t         *p_port_cm;\r
-       ib_ca_attr_t            *p_ca_attr;\r
-       ib_qp_mod_t                     qp_mod;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       status = __get_port_attr( &p_conn->new_alt_path.sgid,\r
-               p_conn->new_alt_path.slid, &p_port_cm, &p_ca_attr );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("__get_port_attr returned %s.\n", ib_get_err_str(status)) );\r
-               return status;\r
-       }\r
-\r
-       /* Setup the alt address vector */\r
-       cl_memclr( &qp_mod, sizeof( ib_qp_mod_t ) );\r
-       qp_mod.state.rts.opts = IB_MOD_QP_ALTERNATE_AV | IB_MOD_QP_APM_STATE;\r
-       cm_save_path_av( &p_ca_attr->p_port_attr[p_port_cm->port_idx],\r
-               &p_conn->new_alt_path, p_conn->p_req_info->qp_mod_rts.state.rts.retry_cnt,\r
-               p_conn->p_req_info->qp_mod_rts.state.rts.rnr_retry_cnt,\r
-               &qp_mod.state.rts.alternate_av );\r
-\r
-       qp_mod.state.rts.apm_state = IB_APM_REARM;\r
-       qp_mod.req_state = IB_QPS_RTS;\r
-       status = ib_modify_qp( p_conn->h_qp, &qp_mod );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("ib_modify_qp for LAP returned %s.\n", ib_get_err_str(status)) );\r
-               return status;\r
-       }\r
-\r
-       cl_memcpy( &p_conn->path[(p_conn->idx_primary + 1) & 0x1],\r
-               &p_conn->new_alt_path, sizeof(ib_path_rec_t) );\r
-       AL_EXIT( AL_DBG_CM );\r
-       return IB_SUCCESS;\r
-}\r
-\r
-\r
-void\r
-__process_cm_apr(\r
-       IN                              cl_async_proc_item_t            *p_item )\r
-{\r
-       cm_port_agent_t *p_port_cm;\r
-       mad_cm_apr_t    *p_apr;\r
-       cm_async_mad_t  *p_async_mad;\r
-       cl_map_item_t   *p_map_item;\r
-       al_conn_t               *p_conn;\r
-       uint64_t                key;\r
-       ib_cm_apr_rec_t apr_rec;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_async_mad = PARENT_STRUCT( p_item, cm_async_mad_t, item );\r
-       p_port_cm = p_async_mad->p_port_cm;\r
-       p_apr = (mad_cm_apr_t*)p_async_mad->p_mad->p_mad_buf;\r
-\r
-       key = ((uint64_t)p_apr->remote_comm_id << 32) |\r
-               ((uint64_t)p_apr->local_comm_id );\r
-       /* Find the connection by local connection ID. */\r
-       cl_spinlock_acquire( &gp_cm->obj.lock );\r
-       p_map_item = cl_qmap_get( &gp_cm->conn_map, key );\r
-       if( p_map_item == cl_qmap_end( &gp_cm->conn_map ) )\r
-       {\r
-               cl_spinlock_release( &gp_cm->obj.lock );\r
-               AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_CM,\r
-                       ("APR received that could not be matched.\n") );\r
-               ib_put_mad( p_async_mad->p_mad );\r
-               cl_free( p_async_mad );\r
-               return;\r
-       }\r
-\r
-       p_conn = PARENT_STRUCT( p_map_item, al_conn_t, map_item );\r
-\r
-       __ref_conn( p_conn );\r
-       cl_spinlock_release( &gp_cm->obj.lock );\r
-\r
-       cm_res_acquire( p_conn );\r
-\r
-       switch( p_conn->state )\r
-       {\r
-       case CM_CONN_LAP_SENT:\r
-               /* Cancel sending the LAP. */\r
-               ib_cancel_mad( p_conn->h_mad_svc, p_conn->p_send_mad );\r
-               p_conn->p_send_mad = NULL;\r
-\r
-               /* Fall through to handle the callback. */\r
-       case CM_CONN_LAP_MRA_RCVD:\r
-               cl_memclr( &apr_rec, sizeof( ib_cm_apr_rec_t ) );\r
-               apr_rec.h_qp = p_conn->h_qp;\r
-               apr_rec.qp_context = p_conn->h_qp->obj.context;\r
-               apr_rec.p_info = (const uint8_t*)&p_apr->info;\r
-               apr_rec.info_length = p_apr->info_len;\r
-               apr_rec.p_apr_pdata = p_apr->pdata;\r
-               apr_rec.apr_status = p_apr->status;\r
-\r
-               if( apr_rec.apr_status == IB_AP_SUCCESS )\r
-               {\r
-                       apr_rec.cm_status = __cm_lap_qp( p_conn );\r
-               }\r
-               else\r
-               {\r
-                       apr_rec.cm_status = IB_ERROR;\r
-               }\r
-               cm_res_release( p_conn );\r
-               p_conn->pfn_cm_apr_cb( &apr_rec );\r
-               break;\r
-\r
-       default:\r
-               cm_res_release( p_conn );\r
-               AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_CM,\r
-                       ("APR received in invalid state.\n") );\r
-               break;\r
-       }\r
-       __deref_conn( p_conn );\r
-       ib_put_mad( p_async_mad->p_mad );\r
-       cl_free( p_async_mad );\r
-}\r
-\r
-\r
-/*\r
- * Callback to process a disconnection timeout due to not receiving the DREP\r
- * within allowable time.\r
- */\r
-void\r
-__proc_dconn_timeout(\r
-       IN                              cl_async_proc_item_t*           p_item )\r
-{\r
-       al_conn_t                       *p_conn;\r
-       ib_cm_drep_rec_t        drep_rec;\r
-       ib_cm_drep_t            cm_drep;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_conn = PARENT_STRUCT( p_item, al_conn_t, timeout_item );\r
-\r
-       cm_res_acquire( p_conn );\r
-\r
-       switch( p_conn->state )\r
-       {\r
-       case CM_CONN_DREQ_SENT:\r
-               /* No response.  We're done.  Deliver a DREP callback. */\r
-               cl_memclr( &drep_rec, sizeof( ib_cm_drep_rec_t ) );\r
-               drep_rec.h_qp = p_conn->h_qp;\r
-               drep_rec.qp_context = p_conn->h_qp->obj.context;\r
-               drep_rec.cm_status = IB_TIMEOUT;\r
-\r
-               /*\r
-                * Format a DREP message in case a DREQ is received while\r
-                * the connection is in the timewait state.\r
-                */\r
-               cl_memclr( &cm_drep, sizeof( ib_cm_drep_t ) );\r
-               __format_mad_drep( &cm_drep, p_conn );\r
-\r
-               /*\r
-                * Release the connection now.  Note that we still hold a reference\r
-                * on p_conn from trying to send the DREQ.\r
-                */\r
-               __conn_release( p_conn );\r
-               cm_res_release( p_conn );\r
-\r
-               /* Call the user back. */\r
-               p_conn->pfn_cm_drep_cb( &drep_rec );\r
-               break;\r
-\r
-       default:\r
-               /*\r
-                * Something changed the state.  The DREP was likely received\r
-                * after timing out, but before we could process the timeout.\r
-                */\r
-               cm_res_release( p_conn );\r
-               break;\r
-       }\r
-\r
-       /* Release the reference taken when sending. */\r
-       __deref_conn( p_conn );\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-/*\r
- * Formats a REQ mad's path information given a path record.\r
- */\r
-ib_api_status_t\r
-__format_mad_req_path(\r
-       IN              const   ib_path_rec_t* const            p_path_rec,\r
-       IN              const   uint8_t                                         ack_delay,\r
-               OUT                     req_path_info_t* const          p_req_path )\r
-{\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_req_path->local_lid = p_path_rec->slid;\r
-       p_req_path->remote_lid = p_path_rec->dlid;\r
-       p_req_path->local_gid = p_path_rec->sgid;\r
-       p_req_path->remote_gid = p_path_rec->dgid;\r
-\r
-       conn_req_path_set_flow_lbl( ib_path_rec_flow_lbl( p_path_rec ),\r
-               p_req_path );\r
-       conn_req_path_set_pkt_rate( ib_path_rec_rate( p_path_rec ),\r
-               p_req_path );\r
-\r
-       /* Traffic class & hop limit */\r
-       p_req_path->traffic_class = p_path_rec->tclass;\r
-       p_req_path->hop_limit = ib_path_rec_hop_limit( p_path_rec );\r
-\r
-       /* SL & Subnet Local fields */\r
-       conn_req_path_set_svc_lvl( ib_path_rec_sl( p_path_rec ),\r
-               p_req_path );\r
-       conn_req_path_set_subn_lcl(\r
-               ib_gid_is_link_local( &p_path_rec->dgid ), p_req_path );\r
-\r
-       conn_req_path_set_lcl_ack_timeout( cm_local_ack_timeout(\r
-               ib_path_rec_pkt_life( p_path_rec ), ack_delay ), p_req_path );\r
-\r
-       conn_req_path_clr_rsvd_fields( p_req_path );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return IB_SUCCESS;\r
-}\r
-\r
-\r
-ib_api_status_t\r
-__format_mad_req(\r
-       IN              const   ib_cm_req_t* const                      p_cm_req,\r
-       IN      OUT                     al_conn_t* const                        p_conn )\r
-{\r
-       ib_api_status_t status;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       if( p_cm_req->p_alt_path )\r
-       {\r
-               /* MTUs must match since they are specified only once. */\r
-               if( ib_path_rec_mtu( p_cm_req->p_primary_path ) !=\r
-                       ib_path_rec_mtu( p_cm_req->p_alt_path ) )\r
-               {\r
-                       AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                               ("Mismatched primary and alternate path MTUs.\n") );\r
-                       return IB_INVALID_SETTING;\r
-               }\r
-\r
-               /* Format the alternate path. */\r
-               status = __format_mad_req_path( p_cm_req->p_alt_path,\r
-                       p_conn->p_req_info->p_ca_attr->local_ack_delay,\r
-                       &p_conn->mads.req.alternate_path );\r
-\r
-               if( status != IB_SUCCESS )\r
-               {\r
-                       AL_EXIT( AL_DBG_ERROR );\r
-                       return status;\r
-               }\r
-       }\r
-       else\r
-       {\r
-               cl_memclr( &p_conn->mads.req.alternate_path,\r
-                       sizeof( req_path_info_t ) );\r
-       }\r
-\r
-       /* Format the primary path. */\r
-       status = __format_mad_req_path( p_cm_req->p_primary_path,\r
-               p_conn->p_req_info->p_ca_attr->local_ack_delay,\r
-               &p_conn->mads.req.primary_path );\r
-\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               AL_EXIT( AL_DBG_ERROR );\r
-               return status;\r
-       }\r
-\r
-       /* Format the rest of the REQ. */\r
-       p_conn->mads.req.hdr.attr_id = CM_REQ_ATTR_ID;\r
-       p_conn->mads.req.local_comm_id = p_conn->local_comm_id;\r
-       p_conn->mads.req.sid = p_cm_req->svc_id;\r
-       p_conn->mads.req.local_ca_guid = p_cm_req->h_qp->obj.p_ci_ca->verbs.guid;\r
-\r
-       conn_req_set_lcl_qpn( p_conn->p_req_info->local_qpn, &p_conn->mads.req );\r
-       conn_req_set_resp_res( p_cm_req->resp_res, &p_conn->mads.req );\r
-       conn_req_set_init_depth( p_cm_req->init_depth, &p_conn->mads.req );\r
-       conn_req_set_remote_resp_timeout( p_cm_req->remote_resp_timeout,\r
-               &p_conn->mads.req );\r
-       conn_req_set_qp_type( p_cm_req->h_qp->type, &p_conn->mads.req );\r
-       conn_req_set_flow_ctrl( p_cm_req->flow_ctrl, &p_conn->mads.req );\r
-       conn_req_set_starting_psn( p_conn->p_req_info->local_qpn,\r
-               &p_conn->mads.req );\r
-\r
-       conn_req_set_lcl_resp_timeout( p_cm_req->local_resp_timeout,\r
-               &p_conn->mads.req );\r
-       conn_req_set_retry_cnt( p_cm_req->retry_cnt, &p_conn->mads.req );\r
-\r
-       p_conn->mads.req.pkey = p_cm_req->p_primary_path->pkey;\r
-\r
-       conn_req_set_mtu( ib_path_rec_mtu( p_cm_req->p_primary_path ),\r
-               &p_conn->mads.req );\r
-       conn_req_set_rnr_retry_cnt( p_cm_req->rnr_retry_cnt,\r
-               &p_conn->mads.req );\r
-\r
-       conn_req_set_max_cm_retries( p_cm_req->max_cm_retries, &p_conn->mads.req );\r
-       conn_req_set_pdata(p_cm_req->p_req_pdata, p_cm_req->req_length,\r
-               &p_conn->mads.req );\r
-\r
-       conn_req_clr_rsvd_fields( &p_conn->mads.req );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return IB_SUCCESS;\r
-}\r
-\r
-\r
-ib_api_status_t\r
-__format_mad_rep(\r
-       IN              const   ib_cm_rep_t* const                      p_cm_rep,\r
-       IN      OUT                     al_conn_t* const                        p_conn )\r
-{\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_conn->mads.rep.hdr.attr_id = CM_REP_ATTR_ID;\r
-       p_conn->mads.rep.local_comm_id = p_conn->local_comm_id;\r
-       p_conn->mads.rep.remote_comm_id = p_conn->remote_comm_id;\r
-       conn_rep_set_lcl_qpn( p_conn->p_req_info->local_qpn, &p_conn->mads.rep );\r
-       conn_rep_set_starting_psn( p_conn->p_req_info->local_qpn,\r
-               &p_conn->mads.rep );\r
-\r
-       /* Check the CA's responder resource max and trim if necessary. */\r
-       if( (p_conn->p_req_info->p_ca_attr->max_qp_resp_res <\r
-               p_conn->p_req_info->qp_mod_rtr.state.rtr.resp_res) )\r
-       {\r
-               /*\r
-                * The CA cannot handle the requested responder resources.\r
-                * Set the response to the CA's maximum.\r
-                */\r
-               p_conn->mads.rep.resp_resources = \r
-                       p_conn->p_req_info->p_ca_attr->max_qp_resp_res;\r
-       }\r
-       else\r
-       {\r
-               /* The CA supports the requested responder resources. */\r
-               p_conn->mads.rep.resp_resources = \r
-                       p_conn->p_req_info->qp_mod_rtr.state.rtr.resp_res;\r
-       }\r
-\r
-       p_conn->mads.rep.initiator_depth = p_cm_rep->init_depth;\r
-\r
-       conn_rep_set_target_ack_delay( p_cm_rep->target_ack_delay,\r
-               &p_conn->mads.rep );\r
-       conn_rep_set_failover( p_cm_rep->failover_accepted, &p_conn->mads.rep );\r
-       conn_rep_set_e2e_flow_ctl( p_cm_rep->flow_ctrl, &p_conn->mads.rep );\r
-\r
-       conn_rep_set_rnr_retry_cnt( (uint8_t)(p_cm_rep->rnr_retry_cnt & 0x07),\r
-               &p_conn->mads.rep );\r
-\r
-       p_conn->mads.rep.local_ca_guid = p_conn->p_req_info->p_ca_attr->ca_guid;\r
-\r
-       conn_rep_set_pdata( p_cm_rep->p_rep_pdata, p_cm_rep->rep_length,\r
-               &p_conn->mads.rep );\r
-\r
-       conn_rep_clr_rsvd_fields( &p_conn->mads.rep );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return IB_SUCCESS;\r
-}\r
-\r
-\r
-void\r
-__format_mad_rtu(\r
-       IN              const   ib_cm_rtu_t* const                      p_cm_rtu,\r
-       IN      OUT                     al_conn_t* const                        p_conn )\r
-{\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_conn->mads.rtu.hdr.attr_id = CM_RTU_ATTR_ID;\r
-\r
-       p_conn->mads.rtu.local_comm_id = p_conn->local_comm_id;\r
-       p_conn->mads.rtu.remote_comm_id = p_conn->remote_comm_id;\r
-\r
-       /* copy optional data */\r
-       conn_rtu_set_pdata( p_cm_rtu->p_rtu_pdata, p_cm_rtu->rtu_length,\r
-               &p_conn->mads.rtu );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-\r
-ib_rej_status_t\r
-__conn_save_user_rep(\r
-       IN              const   ib_cm_rep_t* const                      p_cm_rep,\r
-       IN      OUT                     al_conn_t*       const                  p_conn,\r
-               OUT                     cm_port_agent_t** const         pp_port_cm )\r
-{\r
-       ib_api_status_t         status;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       /* Cache the local QPN. */\r
-       p_conn->p_req_info->local_qpn = p_conn->h_qp->num;\r
-\r
-       /* Validate the primary path.  This must be done after binding. */\r
-       status = __validate_primary_path( p_conn, pp_port_cm );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("Primary path validation failed: %s.\n", ib_get_err_str(status)) );\r
-\r
-               /* Reject and abort the connection. */\r
-               return IB_REJ_INVALID_GID;\r
-       }\r
-\r
-       if( p_cm_rep->failover_accepted == IB_FAILOVER_ACCEPT_SUCCESS )\r
-       {\r
-               status = __validate_alt_path( p_conn );\r
-               if( status != IB_SUCCESS )\r
-               {\r
-                       AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                               ("Alternate path validation failed: %s.\n",\r
-                               ib_get_err_str(status)) );\r
-\r
-                       return IB_REJ_INVALID_ALT_GID;\r
-               }\r
-       }\r
-\r
-       /* Update conn info */\r
-       p_conn->p_req_info->pfn_cm_rtu_cb = p_cm_rep->pfn_cm_rtu_cb;\r
-       p_conn->pfn_cm_lap_cb = p_cm_rep->pfn_cm_lap_cb;\r
-       p_conn->pfn_cm_dreq_cb = p_cm_rep->pfn_cm_dreq_cb;\r
-\r
-       if( p_cm_rep->qp_type != p_conn->p_req_info->xport_type )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,      ("qp_type mistach!\n") );\r
-               return IB_REJ_INVALID_XPORT;\r
-       }\r
-\r
-       cm_save_rep_qp_attr( p_cm_rep,\r
-               &p_conn->p_req_info->p_ca_attr->p_port_attr[\r
-               p_conn->p_req_info->port_idx], &p_conn->path[0],\r
-               &p_conn->path[1], &p_conn->p_req_info->qp_mod_rtr,\r
-               &p_conn->p_req_info->qp_mod_rts );\r
-\r
-       /* Update the QP destruction timeout = timeout x retries + 2 seconds. */\r
-       set_al_obj_timeout( &p_cm_rep->h_qp->obj,\r
-               p_conn->retry_timeout * p_conn->max_cm_retries + 2000 );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return 0;\r
-}\r
-\r
-\r
-\r
-ib_api_status_t\r
-__conn_save_user_rtu(\r
-       IN              const   ib_cm_rtu_t* const                      p_cm_rtu,\r
-       IN      OUT                     al_conn_t*       const                  p_conn,\r
-               OUT                     cm_port_agent_t** const         pp_port_cm )\r
-{\r
-       ib_api_status_t         status;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       status = __get_port_attr( &p_conn->path[0].sgid, p_conn->path[0].slid,\r
-               pp_port_cm, NULL );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("__get_port_attr returned %s.\n", ib_get_err_str(status)) );\r
-               /*\r
-                * Don't fail the connection since the remote side will repeat\r
-                * the REP perhaps with better luck.\r
-                */\r
-               return status;\r
-       }\r
-\r
-       p_conn->pfn_cm_apr_cb = p_cm_rtu->pfn_cm_apr_cb;\r
-       p_conn->pfn_cm_dreq_cb = p_cm_rtu->pfn_cm_dreq_cb;\r
-\r
-       cm_save_rtu_qp_attr( p_cm_rtu, &p_conn->p_req_info->qp_mod_rtr );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return IB_SUCCESS;\r
-}\r
-\r
-\r
-\r
-/*\r
- * Formats a LAP mad's path information given a path record.\r
- */\r
-ib_api_status_t\r
-__format_mad_lap_path(\r
-       IN              const   ib_path_rec_t* const            p_path_rec,\r
-       IN              const   uint8_t                                         ack_delay,\r
-               OUT                     lap_path_info_t* const          p_lap_path )\r
-{\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_lap_path->local_lid = p_path_rec->slid;\r
-       p_lap_path->remote_lid = p_path_rec->dlid;\r
-       p_lap_path->local_gid = p_path_rec->sgid;\r
-       p_lap_path->remote_gid = p_path_rec->dgid;\r
-\r
-       /* Set Flow Label and Packet Rate */\r
-       conn_lap_path_set_flow_lbl( ib_path_rec_flow_lbl( p_path_rec ),\r
-               p_lap_path );\r
-       conn_lap_path_set_tclass( p_path_rec->tclass, p_lap_path );\r
-\r
-       p_lap_path->hop_limit = ib_path_rec_hop_limit( p_path_rec );\r
-       conn_lap_path_set_pkt_rate( ib_path_rec_rate( p_path_rec ),\r
-               p_lap_path );\r
-\r
-       /* Set SL and Subnet Local */\r
-       conn_lap_path_set_svc_lvl( ib_path_rec_sl( p_path_rec ),\r
-               p_lap_path );\r
-       conn_lap_path_set_subn_lcl(\r
-               ib_gid_is_link_local( &p_path_rec->dgid ), p_lap_path );\r
-\r
-       conn_lap_path_set_lcl_ack_timeout(\r
-               cm_local_ack_timeout( ib_path_rec_pkt_life( p_path_rec ),\r
-               ack_delay ), p_lap_path );\r
-\r
-       conn_lap_path_clr_rsvd_fields( p_lap_path );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return IB_SUCCESS;\r
-}\r
-\r
-\r
-\r
-/*\r
- * Validates the primary path specified for a connection, and stores\r
- * the assocated CA attributes and port index.\r
- */\r
-ib_api_status_t\r
-__validate_lap_path(\r
-       IN                              al_conn_t* const                        p_conn,\r
-               OUT                     cm_port_agent_t** const         pp_port_cm,\r
-               OUT                     uint8_t* const                          p_ack_delay )\r
-{\r
-       ib_api_status_t         status;\r
-       cm_port_agent_t         *p_port_cm;\r
-       ib_ca_attr_t            *p_ca_attr, *p_alt_ca_attr;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       CL_ASSERT( p_conn );\r
-       CL_ASSERT( pp_port_cm );\r
-       CL_ASSERT( p_ack_delay );\r
-\r
-       status = __get_port_attr( &p_conn->path[p_conn->idx_primary].sgid,\r
-               p_conn->path[p_conn->idx_primary].slid, &p_port_cm, &p_ca_attr );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               /* Primary path invalid.  Should have received a path migration. */\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("Primary connection path invalid!\n") );\r
-               return IB_INVALID_SETTING;\r
-       }\r
-\r
-       status = __get_port_attr( &p_conn->new_alt_path.sgid,\r
-               p_conn->new_alt_path.slid, NULL, &p_alt_ca_attr );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               /* Alternate path invalid. */\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("Alternate path invalid!\n") );\r
-               return status;\r
-       }\r
-\r
-       /*\r
-        * The primary path and alternate path are both valid individually.\r
-        * Check that they are valid as a pair.\r
-        */\r
-       if( p_ca_attr->ca_guid != p_alt_ca_attr->ca_guid )\r
-       {\r
-               /* Paths are not on the same CA. */\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("Primary and alternate paths must be on the same CA.\n") );\r
-               return IB_INVALID_SETTING;\r
-       }\r
-\r
-       *p_ack_delay = p_ca_attr->local_ack_delay;\r
-       *pp_port_cm = p_port_cm;\r
-       AL_EXIT( AL_DBG_CM );\r
-       return IB_SUCCESS;\r
-}\r
-\r
-\r
-void\r
-__format_mad_dreq(\r
-       IN              const   ib_cm_dreq_t* const                     p_cm_dreq,\r
-               OUT                     al_conn_t*              const           p_conn )\r
-{\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_conn->mads.dreq.hdr.attr_id = CM_DREQ_ATTR_ID;\r
-       p_conn->mads.dreq.local_comm_id = p_conn->local_comm_id;\r
-       p_conn->mads.dreq.remote_comm_id = p_conn->remote_comm_id;\r
-       conn_dreq_set_remote_qpn( p_conn->remote_qpn, &p_conn->mads.dreq );\r
-       conn_dreq_set_pdata( p_cm_dreq->p_dreq_pdata, p_cm_dreq->dreq_length,\r
-               &p_conn->mads.dreq );\r
-       conn_dreq_clr_rsvd_fields( &p_conn->mads.dreq );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-void\r
-__format_mad_drep(\r
-       IN              const   ib_cm_drep_t*   const           p_cm_drep,\r
-               OUT                     al_conn_t*              const           p_conn )\r
-{\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       p_conn->mads.drep.hdr.attr_id = CM_DREP_ATTR_ID;\r
-       p_conn->mads.drep.local_comm_id = p_conn->local_comm_id;\r
-       p_conn->mads.drep.remote_comm_id = p_conn->remote_comm_id;\r
-       conn_drep_set_pdata( p_cm_drep->p_drep_pdata, p_cm_drep->drep_length,\r
-               &p_conn->mads.drep );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-}\r
-\r
-\r
-ib_api_status_t\r
-cm_conn_mra(\r
-       IN                              al_conn_t*       const                  p_conn,\r
-       IN              const   ib_cm_mra_t* const                      p_cm_mra )\r
-{\r
-       ib_api_status_t         status;\r
-       cm_port_agent_t         *p_port_cm;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
-\r
-       switch( p_conn->state )\r
-       {\r
-       case CM_CONN_REQ_RCVD:\r
-               p_conn->state = CM_CONN_REQ_MRA_SENT;\r
-       case CM_CONN_REQ_MRA_SENT:\r
-               conn_mra_set_msg_mraed( 0, &p_conn->mads.mra );\r
-               break;\r
-\r
-       case CM_CONN_REP_RCVD:\r
-               p_conn->state = CM_CONN_REP_MRA_SENT;\r
-       case CM_CONN_REP_MRA_SENT:\r
-               conn_mra_set_msg_mraed( 1, &p_conn->mads.mra );\r
-               break;\r
-\r
-       case CM_CONN_LAP_RCVD:\r
-               p_conn->state = CM_CONN_LAP_MRA_SENT;\r
-       case CM_CONN_LAP_MRA_SENT:\r
-               conn_mra_set_msg_mraed( 2, &p_conn->mads.mra );\r
-               break;\r
-\r
-       default:\r
-               /* Invalid state.  Fail the request. */\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("Invalid state for sending MRA.\n") );\r
-               return IB_INVALID_STATE;\r
-       }\r
-\r
-       p_conn->mads.mra.hdr.attr_id = CM_MRA_ATTR_ID;\r
-\r
-       p_conn->mads.mra.local_comm_id = p_conn->local_comm_id;\r
-       p_conn->mads.mra.remote_comm_id = p_conn->remote_comm_id;\r
-       conn_mra_set_svc_timeout( p_cm_mra->svc_timeout, &p_conn->mads.mra );\r
-       status = conn_mra_set_pdata( p_cm_mra->p_mra_pdata, p_cm_mra->mra_length,\r
-               &p_conn->mads.mra );\r
-       if( status != IB_SUCCESS )\r
-               return status;\r
-       conn_mra_clr_rsvd_fields( &p_conn->mads.mra );\r
-\r
-       status = __get_port_attr( &p_conn->path[p_conn->idx_primary].sgid,\r
-               p_conn->path[p_conn->idx_primary].slid, &p_port_cm, NULL );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("__get_port_attr for MRA returned %s.\n", ib_get_err_str(status)) );\r
-               return status;\r
-       }\r
-\r
-       status = __cm_send( p_port_cm, p_conn );\r
-\r
-       AL_EXIT( AL_DBG_CM );\r
-       return status;\r
-}\r
-\r
-\r
-\r
-/*\r
- * Abort a connection.\r
- */\r
-void\r
-__conn_abort(\r
-       IN  &nb