[ofw] [PATCH 3/7 v3] ib/cm: export CM only interface

Hefty, Sean sean.hefty at intel.com
Fri Jan 23 17:36:09 PST 2009


To support WinVerbs and a future OFED libibcm compatibility library (requires
a new library and driver), export a new IB CM interface.  The interface sits
above the existing communication endpoint (CEP) manager.  This allows the
interface to only support IB CM functionality.

Rather than exposing low-level CM related MADs as done in the initial posting
of the code, a cleaner, more self-contained interface was defined.
The interface is based on the requirements of the CM as defined by the
IB architecture.  The interface does not assume that the underlying CM has
direct access to QP data structures or user event queues.

Signed-off-by: Sean Hefty <sean.hefty at intel.com>
---
This patch resolves all pending comments and will be what I commit to the trunk.

diffs from v2

* Renamed kal_*_cep functions to kal_cep_* for consistency.

* Added special call for ND use when sending CM replies:
  kal_cep_config_pre_rep_copy_cid().  That should be a descriptive
  enough name.  :)

* Changed kal_cep_config() to return a void.  The caller is responsible
  for ensuring that the CID is valid, which is true for current usage.

--- trunk\inc\kernel\iba\ib_cm_ifc.h    1969-12-31 16:00:00.000000000 -0800
+++ branches\winverbs\inc\kernel\iba\ib_cm_ifc.h        2008-11-20 23:21:48.890625000 -0800
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2008 Intel Corporation.  All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _ib_cm_ifc_h_
+#define _ib_cm_ifc_h_
+
+#include <initguid.h>
+#include <iba/ib_al_ifc.h>
+#include <iba/ib_types.h>
+#include <iba/ib_al.h>
+
+struct _iba_cm_event;
+
+typedef struct _iba_cm_id
+{
+       void            *context;
+       NTSTATUS        (*callback)(struct _iba_cm_id *p_id, struct _iba_cm_event *p_event);
+       net32_t         cid;
+
+}      iba_cm_id;
+
+typedef struct _iba_cm_req
+{
+       ib_net64_t                                      service_id;
+
+       ib_path_rec_t                           *p_primary_path;
+       ib_path_rec_t                           *p_alt_path;
+
+       net32_t                                         qpn;
+       ib_qp_type_t                            qp_type;
+       net32_t                                         starting_psn;
+
+       void                                            *p_pdata;
+       uint8_t                                         pdata_len;
+
+       uint8_t                                         max_cm_retries;
+       uint8_t                                         resp_res;
+       uint8_t                                         init_depth;
+       uint8_t                                         remote_resp_timeout;
+       uint8_t                                         flow_ctrl;
+       uint8_t                                         local_resp_timeout;
+       uint8_t                                         rnr_retry_cnt;
+       uint8_t                                         retry_cnt;
+       uint8_t                                         srq;
+
+}      iba_cm_req;
+
+typedef struct _iba_cm_req_event
+{
+       iba_cm_req                                      req;
+       net64_t                                         local_ca_guid;
+       net64_t                                         remote_ca_guid;
+       uint16_t                                        pkey_index;
+       uint8_t                                         port_num;
+
+}      iba_cm_req_event;
+
+typedef struct _iba_cm_rep
+{
+       net32_t                                         qpn;
+       net32_t                                         starting_psn;
+
+       void                                            *p_pdata;
+       uint8_t                                         pdata_len;
+
+       ib_cm_failover_t                        failover_accepted;
+       uint8_t                                         resp_res;
+       uint8_t                                         init_depth;
+       uint8_t                                         flow_ctrl;
+       uint8_t                                         rnr_retry_cnt;
+       uint8_t                                         srq;
+
+}      iba_cm_rep;
+
+typedef struct _iba_cm_rep_event
+{
+       iba_cm_rep                                      rep;
+       net64_t                                         ca_guid;
+       uint8_t                                         target_ack_delay;
+
+}      iba_cm_rep_event;
+
+typedef struct _iba_cm_pdata
+{
+       void                                            *p_pdata;
+       uint8_t                                         pdata_len;
+
+}      iba_cm_pdata;
+typedef iba_cm_pdata                   iba_cm_rtu_event;
+typedef iba_cm_pdata                   iba_cm_dreq_event;
+typedef iba_cm_pdata                   iba_cm_drep_event;
+
+typedef struct _iba_cm_rej_event
+{
+       void                                            *ari;
+       void                                            *p_pdata;
+       ib_rej_status_t                         reason;
+       uint8_t                                         ari_length;
+       uint8_t                                         pdata_len;
+
+}      iba_cm_rej_event;
+
+typedef struct _iba_cm_mra_event
+{
+       void                                            *p_pdata;
+       uint8_t                                         pdata_len;
+       uint8_t                                         service_timeout;
+
+}      iba_cm_mra_event;
+
+typedef struct _iba_cm_lap
+{
+       ib_path_rec_t                           *p_alt_path;
+       void                                            *p_pdata;
+       uint8_t                                         pdata_len;
+       uint8_t                                         remote_resp_timeout;
+
+}      iba_cm_lap;
+typedef iba_cm_lap iba_cm_lap_event;
+
+typedef struct _iba_cm_apr
+{
+       void                                            *p_pdata;
+       ib_apr_info_t                           *p_info;
+       uint8_t                                         pdata_len;
+       uint8_t                                         info_length;
+       ib_apr_status_t                         status;
+
+}      iba_cm_apr;
+typedef iba_cm_apr iba_cm_apr_event;
+
+typedef struct _iba_cm_sidr_req
+{
+       ib_net64_t                                      service_id;
+       ib_path_rec_t                           *p_path;
+       void                                            *p_pdata;
+       uint8_t                                         pdata_len;
+       uint8_t                                         max_cm_retries;
+       uint32_t                                        timeout;
+
+}      iba_cm_sidr_req;
+
+typedef struct _iba_cm_sidr_req_event
+{
+       iba_cm_sidr_req                         sidr_req;
+       net64_t                                         ca_guid;
+       uint16_t                                        pkey_index;
+       uint8_t                                         port_num;
+
+}      iba_cm_sidr_req_event;
+
+typedef struct _iba_cm_sidr_rep
+{
+       net32_t                                         qpn;
+       net32_t                                         qkey;
+       void                                            *p_pdata;
+       void                                            *p_info;
+       uint8_t                                         pdata_len;
+       uint8_t                                         info_len;
+       ib_sidr_status_t                        status;
+
+}      iba_cm_sidr_rep;
+typedef iba_cm_sidr_rep iba_cm_sidr_rep_event;
+
+typedef enum _iba_cm_event_type
+{
+       iba_cm_req_error,
+       iba_cm_req_received,
+       iba_cm_rep_error,
+       iba_cm_rep_received,
+       iba_cm_rtu_received,
+       iba_cm_dreq_error,
+       iba_cm_dreq_received,
+       iba_cm_drep_received,
+       iba_cm_rej_received,
+       iba_cm_mra_received,
+       iba_cm_lap_error,
+       iba_cm_lap_received,
+       iba_cm_apr_received,
+       iba_cm_sidr_req_error,
+       iba_cm_sidr_req_received,
+       iba_cm_sidr_rep_received
+
+}      iba_cm_event_type;
+
+typedef struct _iba_cm_event
+{
+       iba_cm_event_type                       type;
+       union
+       {
+               iba_cm_req_event                req;
+               iba_cm_rep_event                rep;
+               iba_cm_rtu_event                rtu;
+               iba_cm_dreq_event               dreq;
+               iba_cm_drep_event               drep;
+               iba_cm_rej_event                rej;
+               iba_cm_mra_event                mra;
+               iba_cm_lap_event                lap;
+               iba_cm_apr_event                apr;
+               iba_cm_sidr_req_event   sidr_req;
+               iba_cm_sidr_rep_event   sidr_rep;
+
+       }       data;
+
+}      iba_cm_event;
+
+typedef struct _iba_cm_interface
+{
+       NTSTATUS                (*create_id)(NTSTATUS (*callback)(iba_cm_id *p_id,
+                                                                                                         iba_cm_event *p_event),
+                                                                void *context, iba_cm_id **pp_id);
+       void                    (*destroy_id)(iba_cm_id *p_id);
+
+       NTSTATUS                (*listen)(iba_cm_id *p_id, net64_t service_id, void *p_compare_buf,
+                                                         uint8_t compare_len, uint8_t compare_offset);
+
+       NTSTATUS                (*send_req)(iba_cm_id *p_id, iba_cm_req *p_req);
+       NTSTATUS                (*send_rep)(iba_cm_id *p_id, iba_cm_rep *p_rep);
+       NTSTATUS                (*send_rtu)(iba_cm_id *p_id, void *p_pdata, uint8_t pdata_len);
+
+       NTSTATUS                (*send_dreq)(iba_cm_id *p_id, void *p_pdata, uint8_t pdata_len);
+       NTSTATUS                (*send_drep)(iba_cm_id *p_id, void *p_pdata, uint8_t pdata_len);
+
+       NTSTATUS                (*send_rej)(iba_cm_id *p_id, ib_rej_status_t status,
+                                                               void *p_ari, uint8_t ari_len,
+                                                               void *p_pdata, uint8_t pdata_len);
+       NTSTATUS                (*send_mra)(iba_cm_id *p_id, uint8_t service_timeout,
+                                                               void *p_pdata, uint8_t pdata_len);
+
+       NTSTATUS                (*send_lap)(iba_cm_id *p_id, iba_cm_lap *p_lap);
+       NTSTATUS                (*send_apr)(iba_cm_id *p_id, iba_cm_apr *p_apr);
+
+       NTSTATUS                (*send_sidr_req)(iba_cm_id *p_id, iba_cm_sidr_req *p_req);
+       NTSTATUS                (*send_sidr_rep)(iba_cm_id *p_id, iba_cm_sidr_rep *p_rep);
+
+       NTSTATUS                (*get_qp_attr)(iba_cm_id *p_id, ib_qp_state_t state,
+                                                                  ib_qp_mod_t *p_attr);
+
+       NTSTATUS                (*migrate)(iba_cm_id *p_id);
+       NTSTATUS                (*established)(iba_cm_id *p_id);
+
+}      iba_cm_interface;
+
+static inline USHORT IbaCmVersion(UINT8 Major, UINT8 Minor)
+{
+       return ((USHORT) Major << 8) | ((USHORT) Minor);
+}
+
+static inline UINT8 IbaCmVersionMajor(USHORT Version)
+{
+       return (UINT8) (Version >> 8);
+}
+
+static inline UINT8 IbaCmVersionMinor(USHORT Version)
+{
+       return (UINT8) Version;
+}
+
+// {EACC1466-BB2D-4478-B5BE-40EDF7EE08AB}
+DEFINE_GUID(GUID_INFINIBAND_INTERFACE_CM, 0xeacc1466, 0xbb2d, 0x4478,
+                       0xb5, 0xbe, 0x40, 0xed, 0xf7, 0xee, 0x8, 0xab);
+
+typedef struct _INFINIBAND_INTERFACE_CM
+{
+       INTERFACE                       InterfaceHeader;
+       iba_cm_interface        CM;
+
+}      INFINIBAND_INTERFACE_CM;
+
+#endif // _ib_cm_ifc_h_
--- trunk\core\al\kernel\al_cm.c        1969-12-31 16:00:00.000000000 -0800
+++ branches\winverbs\core\al\kernel\al_cm.c    2009-01-20 16:01:24.451979200 -0800
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2008 Intel Corporation.  All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <iba/ib_cm_ifc.h>
+#include "al_cm_cep.h"
+#include "al_mgr.h"
+#include "al_proxy.h"
+#include "al_cm_conn.h"
+#include "al_cm_sidr.h"
+
+typedef struct _iba_cm_id_priv
+{
+       iba_cm_id       id;
+       KEVENT          destroy_event;
+
+}      iba_cm_id_priv;
+
+static iba_cm_id*
+cm_alloc_id(NTSTATUS (*callback)(iba_cm_id *p_id, iba_cm_event *p_event),
+                       void *context)
+{
+       iba_cm_id_priv  *id;
+
+       id = ExAllocatePoolWithTag(NonPagedPool, sizeof(iba_cm_id_priv), 'mcbi');
+       if (id == NULL) {
+               return NULL;
+       }
+
+       KeInitializeEvent(&id->destroy_event, NotificationEvent, FALSE);
+       id->id.callback = callback;
+       id->id.context = context;
+       return &id->id;
+}
+
+static void
+cm_free_id(iba_cm_id *id)
+{
+       ExFreePool(CONTAINING_RECORD(id, iba_cm_id_priv, id));
+}
+
+static void
+cm_destroy_handler(void *context)
+{
+       iba_cm_id_priv  *id = context;
+       KeSetEvent(&id->destroy_event, 0, FALSE);
+}
+
+static void
+cm_cep_handler(const ib_al_handle_t h_al, const net32_t cid)
+{
+       void                            *context;
+       net32_t                         new_cid;
+       ib_mad_element_t        *mad;
+       iba_cm_id                       *id, *listen_id;
+       iba_cm_event            event;
+       NTSTATUS                        status;
+
+       while (al_cep_poll(h_al, cid, &context, &new_cid, &mad) == IB_SUCCESS) {
+
+               if (new_cid == AL_INVALID_CID) {
+                       id = (iba_cm_id *) context;
+               } else {
+                       listen_id = (iba_cm_id *) context;
+
+                       id = cm_alloc_id(listen_id->callback, listen_id);
+                       if (id == NULL) {
+                               kal_destroy_cep(h_al, new_cid);
+                               ib_put_mad(mad);
+                               continue;
+                       }
+
+                       kal_config_cep(h_al, new_cid, cm_cep_handler, id, cm_destroy_handler);
+                       id->cid = new_cid;
+               }
+
+               kal_cep_format_event(h_al, id->cid, mad, &event);
+               status = id->callback(id, &event);
+               if (!NT_SUCCESS(status)) {
+                       kal_config_cep(h_al, new_cid, NULL, NULL, NULL);
+                       kal_destroy_cep(h_al, id->cid);
+                       cm_free_id(id);
+               }
+               ib_put_mad(mad);
+       }
+}
+
+static NTSTATUS
+cm_create_id(NTSTATUS (*callback)(iba_cm_id *p_id, iba_cm_event *p_event),
+                        void *context, iba_cm_id **pp_id)
+{
+       iba_cm_id               *id;
+       ib_api_status_t ib_status;
+
+       id = cm_alloc_id(callback, context);
+       if (id == NULL) {
+               return STATUS_NO_MEMORY;
+       }
+
+       ib_status = kal_alloc_cep(gh_al, &id->cid);
+       if (ib_status != IB_SUCCESS) {
+               cm_free_id(id);
+               return ib_to_ntstatus(ib_status);
+       }
+
+       kal_config_cep(gh_al, id->cid, cm_cep_handler, id, cm_destroy_handler);
+       *pp_id = id;
+       return STATUS_SUCCESS;
+}
+
+static void
+cm_destroy_id(iba_cm_id *p_id)
+{
+       iba_cm_id_priv  *id;
+
+       id = CONTAINING_RECORD(p_id, iba_cm_id_priv, id);
+       kal_destroy_cep(gh_al, p_id->cid);
+       KeWaitForSingleObject(&id->destroy_event, Executive, KernelMode, FALSE, NULL);
+       cm_free_id(p_id);
+}
+
+static NTSTATUS
+cm_listen(iba_cm_id *p_id, net64_t service_id, void *p_compare_buf,
+                 uint8_t compare_len, uint8_t compare_offset)
+{
+       ib_cep_listen_t info;
+       ib_api_status_t ib_status;
+
+       info.svc_id = service_id;
+       info.port_guid = IB_ALL_PORTS;
+       info.p_cmp_buf = p_compare_buf;
+       info.cmp_len = compare_len;
+       info.cmp_offset = compare_offset;
+
+       ib_status = al_cep_listen(gh_al, p_id->cid, &info);
+       return ib_to_ntstatus(ib_status);
+}
+
+static NTSTATUS
+cm_send_req(iba_cm_id *p_id, iba_cm_req *p_req)
+{
+       ib_api_status_t ib_status;
+
+       ib_status = kal_cep_pre_req(gh_al, p_id->cid, p_req, 0, NULL);
+       if (ib_status != IB_SUCCESS) {
+               return ib_to_ntstatus(ib_status);
+       }
+
+       ib_status = al_cep_send_req(gh_al, p_id->cid);
+       return ib_to_ntstatus(ib_status);
+}
+
+static NTSTATUS
+cm_send_rep(iba_cm_id *p_id, iba_cm_rep *p_rep)
+{
+       ib_api_status_t ib_status;
+
+       ib_status = kal_cep_pre_rep(gh_al, p_id->cid, p_rep, 0, NULL);
+       if (ib_status != IB_SUCCESS) {
+               return ib_to_ntstatus(ib_status);
+       }
+
+       ib_status = al_cep_send_rep(gh_al, p_id->cid);
+       return ib_to_ntstatus(ib_status);
+}
+
+static NTSTATUS
+cm_send_rtu(iba_cm_id *p_id, void *p_pdata, uint8_t pdata_len)
+{
+       ib_api_status_t ib_status;
+
+       ib_status = al_cep_rtu(gh_al, p_id->cid, p_pdata, pdata_len);
+       return ib_to_ntstatus(ib_status);
+}
+
+static NTSTATUS
+cm_send_dreq(iba_cm_id *p_id, void *p_pdata, uint8_t pdata_len)
+{
+       ib_api_status_t ib_status;
+
+       ib_status = al_cep_dreq(gh_al, p_id->cid, p_pdata, pdata_len);
+       return ib_to_ntstatus(ib_status);
+}
+
+static NTSTATUS
+cm_send_drep(iba_cm_id *p_id, void *p_pdata, uint8_t pdata_len)
+{
+       ib_api_status_t ib_status;
+
+       ib_status = al_cep_drep(gh_al, p_id->cid, p_pdata, pdata_len);
+       return ib_to_ntstatus(ib_status);
+}
+
+static NTSTATUS
+cm_send_rej(iba_cm_id *p_id, ib_rej_status_t status,
+                       void *p_ari, uint8_t ari_len,
+                       void *p_pdata, uint8_t pdata_len)
+{
+       ib_api_status_t ib_status;
+
+       ib_status = al_cep_rej(gh_al, p_id->cid, status, p_ari, ari_len,
+                                                  p_pdata, pdata_len);
+       return ib_to_ntstatus(ib_status);
+}
+
+static NTSTATUS
+cm_send_mra(iba_cm_id *p_id, uint8_t service_timeout,
+                       void *p_pdata, uint8_t pdata_len)
+{
+       ib_cm_mra_t             mra;
+       ib_api_status_t ib_status;
+
+       mra.svc_timeout = service_timeout;
+       mra.p_mra_pdata = p_pdata;
+       mra.mra_length = pdata_len;
+
+       ib_status = al_cep_mra(gh_al, p_id->cid, &mra);
+       return ib_to_ntstatus(ib_status);
+}
+
+static NTSTATUS
+cm_send_lap(iba_cm_id *p_id, iba_cm_lap *p_lap)
+{
+       ib_cm_lap_t             lap;
+       ib_api_status_t ib_status;
+
+       RtlZeroMemory(&lap, sizeof lap);
+       lap.p_lap_pdata = p_lap->p_pdata;
+       lap.lap_length = p_lap->pdata_len;
+       lap.remote_resp_timeout = p_lap->remote_resp_timeout;
+       lap.p_alt_path = p_lap->p_alt_path;
+
+       ib_status = al_cep_lap(gh_al, p_id->cid, &lap);
+       return ib_to_ntstatus(ib_status);
+}
+
+static NTSTATUS
+cm_send_apr(iba_cm_id *p_id, iba_cm_apr *p_apr)
+{
+       ib_cm_apr_t             apr;
+       ib_qp_mod_t             attr;
+       ib_api_status_t ib_status;
+
+       RtlZeroMemory(&apr, sizeof apr);
+       apr.p_apr_pdata = p_apr->p_pdata;
+       apr.apr_length = p_apr->pdata_len;
+       apr.apr_status = p_apr->status;
+       apr.info_length = p_apr->info_length;
+       apr.p_info = p_apr->p_info;
+
+       ib_status = al_cep_pre_apr(gh_al, p_id->cid, &apr, &attr);
+       if (ib_status != IB_SUCCESS) {
+               return ib_to_ntstatus(ib_status);
+       }
+
+       ib_status = al_cep_send_apr(gh_al, p_id->cid);
+       return ib_to_ntstatus(ib_status);
+}
+
+static NTSTATUS
+cm_send_sidr_req(iba_cm_id *p_id, iba_cm_sidr_req *p_req)
+{
+       UNUSED_PARAM(p_id);
+       UNUSED_PARAM(p_req);
+
+       return STATUS_NOT_SUPPORTED;
+}
+
+static NTSTATUS
+cm_send_sidr_rep(iba_cm_id *p_id, iba_cm_sidr_rep *p_rep)
+{
+       UNUSED_PARAM(p_id);
+       UNUSED_PARAM(p_rep);
+
+       return STATUS_NOT_SUPPORTED;
+}
+
+static NTSTATUS
+cm_get_qp_attr(iba_cm_id *p_id, ib_qp_state_t state, ib_qp_mod_t *p_attr)
+{
+       ib_api_status_t ib_status;
+
+       switch (state) {
+       case IB_QPS_INIT:
+               ib_status = al_cep_get_init_attr(gh_al, p_id->cid, p_attr);
+               break;
+       case IB_QPS_RTR:
+               ib_status = al_cep_get_rtr_attr(gh_al, p_id->cid, p_attr);
+               break;
+       case IB_QPS_RTS:
+               ib_status = al_cep_get_rts_attr(gh_al, p_id->cid, p_attr);
+               break;
+       default:
+               return STATUS_INVALID_PARAMETER;
+       }
+
+       return ib_to_ntstatus(ib_status);
+}
+
+static NTSTATUS
+cm_migrate(iba_cm_id *p_id)
+{
+       ib_api_status_t ib_status;
+
+       ib_status = al_cep_migrate(gh_al, p_id->cid);
+       return ib_to_ntstatus(ib_status);
+}
+
+static NTSTATUS
+cm_establish(iba_cm_id *p_id)
+{
+       ib_api_status_t ib_status;
+
+       ib_status = al_cep_established(gh_al, p_id->cid);
+       return ib_to_ntstatus(ib_status);
+}
+
+void cm_get_interface(iba_cm_interface *p_ifc)
+{
+       p_ifc->create_id = cm_create_id;
+       p_ifc->destroy_id = cm_destroy_id;
+       p_ifc->listen = cm_listen;
+       p_ifc->send_req = cm_send_req;
+       p_ifc->send_rep = cm_send_rep;
+       p_ifc->send_rtu = cm_send_rtu;
+       p_ifc->send_dreq = cm_send_dreq;
+       p_ifc->send_drep = cm_send_drep;
+       p_ifc->send_rej = cm_send_rej;
+       p_ifc->send_mra = cm_send_mra;
+       p_ifc->send_lap = cm_send_lap;
+       p_ifc->send_apr = cm_send_apr;
+       p_ifc->send_sidr_req = cm_send_sidr_req;
+       p_ifc->send_sidr_rep = cm_send_sidr_rep;
+       p_ifc->get_qp_attr = cm_get_qp_attr;
+       p_ifc->migrate = cm_migrate;
+       p_ifc->established = cm_establish;
+}
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/core/al/al_cm_cep.h branches\winverbs/core/al/al_cm_cep.h
--- trunk/core/al/al_cm_cep.h   2008-07-16 08:53:58.172250000 -0700
+++ branches\winverbs/core/al/al_cm_cep.h       2009-01-23 17:00:31.664525900 -0800
@@ -36,10 +36,12 @@
 #ifndef _AL_CM_CEP_H_
 #define _AL_CM_CEP_H_

-
 #include <iba/ib_al.h>
 #include "al_common.h"

+#ifdef CL_KERNEL
+#include <iba/ib_cm_ifc.h>
+#endif

 #define CEP_EVENT_TIMEOUT      0x80000000
 #define CEP_EVENT_RECV         0x40000000
@@ -108,6 +110,21 @@ al_create_cep(
 * event notification.
 *********/

+#ifdef CL_KERNEL
+ib_api_status_t
+kal_cep_alloc(
+       IN                              ib_al_handle_t                          h_al,
+       IN      OUT                     net32_t* const                          p_cid );
+
+void
+kal_cep_config(
+       IN                              ib_al_handle_t                          h_al,
+       IN                              net32_t                                         cid,
+       IN                              al_pfn_cep_cb_t                         pfn_cb,
+       IN                              void*                                           context,
+       IN                              ib_pfn_destroy_cb_t                     pfn_destroy_cb );
+#endif
+
 /* Destruction is asynchronous. */
 void
 al_destroy_cep(
@@ -124,6 +141,16 @@ al_cep_listen(
        IN                              ib_cep_listen_t* const          p_listen_info );


+#ifdef CL_KERNEL
+ib_api_status_t
+kal_cep_pre_req(
+       IN                              ib_al_handle_t                          h_al,
+       IN                              net32_t                                         cid,
+       IN              const   iba_cm_req* const                       p_cm_req,
+       IN                              uint8_t                                         rnr_nak_timeout,
+       IN      OUT                     ib_qp_mod_t* const                      p_init OPTIONAL );
+#endif
+
 ib_api_status_t
 al_cep_pre_req(
        IN                              ib_al_handle_t                          h_al,
@@ -148,22 +175,52 @@ al_cep_pre_rep(
        IN      OUT                     net32_t* const                          p_cid,
                OUT                     ib_qp_mod_t* const                      p_init );

+#ifdef CL_KERNEL
+ib_api_status_t
+kal_cep_pre_rep(
+       IN                              ib_al_handle_t                          h_al,
+       IN                              net32_t                                         cid,
+       IN              const   iba_cm_rep* const                       p_cm_rep,
+       IN                              uint8_t                                         rnr_nak_timeout,
+       IN      OUT                     ib_qp_mod_t* const                      p_init OPTIONAL );
+
 ib_api_status_t
-al_cep_pre_rep_ex(
+kal_cep_config_pre_rep_copy_cid(
        IN                              ib_al_handle_t                          h_al,
        IN                              net32_t                                         cid,
        IN                              al_pfn_cep_cb_t                         pfn_cb,
        IN                              void*                                           context,
-       IN                              ib_pfn_destroy_cb_t                     pfn_destroy_cb OPTIONAL,
-       IN              const   ib_cm_rep_t* const                      p_cm_rep,
+       IN                              ib_pfn_destroy_cb_t                     pfn_destroy_cb,
+       IN              const   iba_cm_rep* const                       p_cm_rep,
+       IN                              uint8_t                                         rnr_nak_timeout,
        IN      OUT                     net32_t* const                          p_cid,
                OUT                     ib_qp_mod_t* const                      p_init );

+void
+kal_cep_destroy(
+       IN                              ib_al_handle_t                          h_al,
+       IN                              net32_t                                         cid );
+#endif
+
 ib_api_status_t
 al_cep_send_rep(
        IN                              ib_al_handle_t                          h_al,
        IN                              net32_t                                         cid );

+#ifdef CL_KERNEL
+void
+kal_cep_format_event(
+       IN                              ib_al_handle_t                          h_al,
+       IN                              net32_t                                         cid,
+       IN                              ib_mad_element_t                        *p_mad,
+       IN      OUT                     iba_cm_event                            *p_event);
+
+ib_api_status_t
+al_cep_get_init_attr(
+       IN                              ib_al_handle_t                          h_al,
+       IN                              net32_t                                         cid,
+               OUT                     ib_qp_mod_t* const                      p_init );
+#endif

 ib_api_status_t
 al_cep_get_rtr_attr(
@@ -271,6 +328,7 @@ al_cep_poll(


 #ifdef CL_KERNEL
+void cm_get_interface(iba_cm_interface *p_ifc);

 NTSTATUS
 al_cep_queue_irp(
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/core/al/kernel/al_cm_cep.c branches\winverbs/core/al/kernel/al_cm_cep.c
--- trunk/core/al/kernel/al_cm_cep.c    2008-07-16 08:53:56.469125000 -0700
+++ branches\winverbs/core/al/kernel/al_cm_cep.c        2009-01-23 17:00:16.945681700 -0800
@@ -36,6 +36,7 @@
 #include <complib/cl_rbmap.h>
 #include <complib/cl_qmap.h>
 #include <complib/cl_spinlock.h>
+#include <iba/ib_cm_ifc.h>
 #include "al_common.h"
 #include "al_cm_cep.h"
 #include "al_cm_conn.h"
@@ -333,7 +334,6 @@ typedef struct _al_kcep
        ib_mad_svc_handle_t                     h_mad_svc;
        ib_mad_element_t                        *p_send_mad;

-       /* Number of outstanding MADs.  Delays destruction of CEP destruction. */
        atomic32_t                                      ref_cnt;

        /* MAD transaction ID to use when sending MADs. */
@@ -367,7 +367,7 @@ typedef struct _al_kcep
        }       mads;

        /*
-        * NDI stuff
+        * NDI stuff - TODO: manage above core kernel CM code
         */

        /* IRP list head */
@@ -1064,7 +1064,8 @@ __req_handler(

        KeAcquireInStackQueuedSpinLockAtDpcLevel( &gp_cep_mgr->lock, &hdl );

-       if( conn_req_get_qp_type( p_req ) > IB_QPT_UNRELIABLE_CONN )
+       if( conn_req_get_qp_type( p_req ) > IB_QPT_UNRELIABLE_CONN ||
+               conn_req_get_lcl_qpn( p_req ) == 0 )
        {
                /* Reserved value.  Reject. */
                AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("Invalid transport type received.\n") );
@@ -3410,6 +3411,7 @@ __cep_queue_mad(
                return IB_INVALID_STATE;
        }

+       // TODO: Remove - manage above core kernel CM code
        /* NDI connection request case */
        if ( p_cep->state == CEP_STATE_LISTEN &&
                (p_cep->sid & ~0x0ffffffI64) == IB_REQ_CM_RDMA_SID_PREFIX )
@@ -3650,6 +3652,47 @@ __bind_cep(
        cl_spinlock_release( &h_al->obj.lock );
 }

+ib_api_status_t
+kal_cep_alloc(
+       IN                              ib_al_handle_t                          h_al,
+       IN      OUT                     net32_t* const                          p_cid )
+{
+       kcep_t                          *p_cep;
+       KLOCK_QUEUE_HANDLE      hdl;
+
+       KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
+       p_cep = __create_cep();
+       KeReleaseInStackQueuedSpinLock( &hdl );
+
+       if( !p_cep )
+               return IB_INSUFFICIENT_MEMORY;
+
+       __bind_cep(p_cep, h_al, NULL, NULL);
+       *p_cid = p_cep->cid;
+       return IB_SUCCESS;
+}
+
+void
+kal_cep_config(
+       IN                              ib_al_handle_t                          h_al,
+       IN                              net32_t                                         cid,
+       IN                              al_pfn_cep_cb_t                         pfn_cb,
+       IN                              void*                                           context,
+       IN                              ib_pfn_destroy_cb_t                     pfn_destroy_cb )
+{
+       kcep_t                          *p_cep;
+       KLOCK_QUEUE_HANDLE      hdl;
+
+       KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
+       p_cep = __lookup_cep( h_al, cid );
+       CL_ASSERT( p_cep );
+
+       p_cep->pfn_cb = pfn_cb;
+       p_cep->context = context;
+       p_cep->pfn_destroy_cb = pfn_destroy_cb;
+
+       KeReleaseInStackQueuedSpinLock( &hdl );
+}

 static inline void
 __unbind_cep(
@@ -3967,10 +4010,12 @@ __cleanup_cep(
                        sizeof(p_cep->local_ca_guid), NULL, 0 );
                break;

-       case CEP_STATE_ESTABLISHED:
-       case CEP_STATE_LAP_RCVD:
        case CEP_STATE_LAP_SENT:
        case CEP_STATE_LAP_MRA_RCVD:
+               ib_cancel_mad( p_cep->h_mad_svc, p_cep->p_send_mad );
+               /* fall through */
+       case CEP_STATE_ESTABLISHED:
+       case CEP_STATE_LAP_RCVD:
        case CEP_STATE_LAP_MRA_SENT:
        case CEP_STATE_PRE_APR:
        case CEP_STATE_PRE_APR_MRA_SENT:
@@ -3980,9 +4025,9 @@ __cleanup_cep(
                /* Fall through. */

        case CEP_STATE_DREQ_SENT:
+               ib_cancel_mad( p_cep->h_mad_svc, p_cep->p_send_mad );
                p_cep->state = CEP_STATE_DREQ_DESTROY;
-               AL_EXIT( AL_DBG_CM );
-               return cl_atomic_dec( &p_cep->ref_cnt );
+               goto out;

        case CEP_STATE_DREQ_RCVD:
                /* Send the DREP. */
@@ -4017,13 +4062,13 @@ __cleanup_cep(
        case CEP_STATE_TIMEWAIT:
                /* Already in timewait - so all is good. */
                p_cep->state = CEP_STATE_DESTROY;
-               AL_EXIT( AL_DBG_CM );
-               return cl_atomic_dec( &p_cep->ref_cnt );
+               goto out;
        }

        p_cep->state = CEP_STATE_DESTROY;
        __insert_timewait( p_cep );

+out:
        AL_EXIT( AL_DBG_CM );
        return cl_atomic_dec( &p_cep->ref_cnt );
 }
@@ -4064,40 +4109,19 @@ al_create_cep(
        IN                              ib_pfn_destroy_cb_t                     pfn_destroy_cb,
        IN      OUT                     net32_t* const                          p_cid )
 {
-       kcep_t                          *p_cep;
-       KLOCK_QUEUE_HANDLE      hdl;
+       ib_api_status_t status;

        AL_ENTER( AL_DBG_CM );
+       CL_ASSERT( h_al );

-       CL_ASSERT( p_cid );
-
-       KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
-       if( *p_cid != AL_INVALID_CID )
+       status = kal_cep_alloc(h_al, p_cid);
+       if ( status == IB_SUCCESS )
        {
-               KeReleaseInStackQueuedSpinLock( &hdl );
-               return IB_RESOURCE_BUSY;
+               kal_cep_config(h_al, *p_cid, pfn_cb, context, pfn_destroy_cb);
        }
-       p_cep = __create_cep();
-       if( !p_cep )
-       {
-               KeReleaseInStackQueuedSpinLock( &hdl );
-               AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("Failed to allocate CEP.\n") );
-               return IB_INSUFFICIENT_MEMORY;
-       }
-
-       __bind_cep( p_cep, h_al, pfn_cb, context );
-
-       p_cep->pfn_destroy_cb = pfn_destroy_cb;
-       *p_cid = p_cep->cid;
-
-       KeReleaseInStackQueuedSpinLock( &hdl );
-
-       AL_PRINT(TRACE_LEVEL_INFORMATION ,AL_DBG_CM ,
-               ("Created CEP with cid %d, h_al %p, context %p \n",
-               p_cep->cid, h_al, p_cep->context ));

        AL_EXIT( AL_DBG_CM );
-       return IB_SUCCESS;
+       return status;
 }


@@ -4107,7 +4131,7 @@ al_destroy_cep(
        IN      OUT                     net32_t* const                          p_cid,
        IN                              boolean_t                                       reusable )
 {
-    net32_t             cid = *p_cid;
+    net32_t             cid;
        kcep_t                          *p_cep;
        KLOCK_QUEUE_HANDLE      hdl;
        void                            *context;
@@ -4123,6 +4147,7 @@ al_destroy_cep(
         * will succeed for it.
         */
        KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
+       cid = *p_cid;
        p_cep = __lookup_cep( h_al, cid );
        if( !p_cep )
        {
@@ -4169,10 +4194,6 @@ al_destroy_cep(

        KeReleaseInStackQueuedSpinLock( &hdl );

-       /*
-        * Done waiting.  Release the reference so the timewait timer callback
-        * can finish cleaning up.
-        */
        if( !ref_cnt && pfn_destroy_cb )
                pfn_destroy_cb( context );

@@ -4183,6 +4204,14 @@ al_destroy_cep(
        AL_EXIT( AL_DBG_CM );
 }

+void
+kal_cep_destroy(
+       IN                              ib_al_handle_t                          h_al,
+       IN                              net32_t                                         cid )
+{
+       al_destroy_cep(h_al, &cid, FALSE);
+}
+

 ib_api_status_t
 al_cep_listen(
@@ -4433,8 +4462,9 @@ __format_req_path(

 static ib_api_status_t
 __format_req(
+       IN                              cep_agent_t* const                      p_port_cep,
        IN                              kcep_t* const                           p_cep,
-       IN              const   ib_cm_req_t* const                      p_cm_req )
+       IN              const   iba_cm_req* const                       p_cm_req )
 {
        ib_api_status_t status;
        mad_cm_req_t*   p_req;
@@ -4453,14 +4483,14 @@ __format_req(

        p_req = (mad_cm_req_t*)p_cep->p_mad->p_mad_buf;

-       ci_ca_lock_attr( p_cm_req->h_qp->obj.p_ci_ca );
+       ci_ca_lock_attr( p_port_cep->h_ca->obj.p_ci_ca );
        /*
         * Store the local CA's ack timeout for use when computing
         * the local ACK timeout.
         */
        p_cep->local_ack_delay =
-               p_cm_req->h_qp->obj.p_ci_ca->p_pnp_attr->local_ack_delay;
-       ci_ca_unlock_attr( p_cm_req->h_qp->obj.p_ci_ca );
+               p_port_cep->h_ca->obj.p_ci_ca->p_pnp_attr->local_ack_delay;
+       ci_ca_unlock_attr( p_port_cep->h_ca->obj.p_ci_ca );

        /* Format the primary path. */
        __format_req_path( p_cm_req->p_primary_path,
@@ -4479,16 +4509,16 @@ __format_req(

        /* Set the local communication in the REQ. */
        p_req->local_comm_id = p_cep->local_comm_id;
-       p_req->sid = p_cm_req->svc_id;
-       p_req->local_ca_guid = p_cm_req->h_qp->obj.p_ci_ca->verbs.guid;
+       p_req->sid = p_cm_req->service_id;
+       p_req->local_ca_guid = p_port_cep->h_ca->obj.p_ci_ca->verbs.guid;

        conn_req_set_lcl_qpn( p_cep->local_qpn, p_req );
        conn_req_set_resp_res( p_cm_req->resp_res, p_req );
        conn_req_set_init_depth( p_cm_req->init_depth, p_req );
        conn_req_set_remote_resp_timeout( p_cm_req->remote_resp_timeout, p_req );
-       conn_req_set_qp_type( p_cm_req->h_qp->type, p_req );
+       conn_req_set_qp_type( p_cm_req->qp_type, p_req );
        conn_req_set_flow_ctrl( p_cm_req->flow_ctrl, p_req );
-       conn_req_set_starting_psn( p_cep->rq_psn, p_req );
+       conn_req_set_starting_psn( p_cm_req->starting_psn, p_req );

        conn_req_set_lcl_resp_timeout( p_cm_req->local_resp_timeout, p_req );
        conn_req_set_retry_cnt( p_cm_req->retry_cnt, p_req );
@@ -4500,7 +4530,7 @@ __format_req(

        conn_req_set_max_cm_retries( p_cm_req->max_cm_retries, p_req );
        status = conn_req_set_pdata(
-               p_cm_req->p_req_pdata, p_cm_req->req_length, p_req );
+               p_cm_req->p_pdata, p_cm_req->pdata_len, p_req );

        conn_req_clr_rsvd_fields( p_req );

@@ -4512,7 +4542,8 @@ __format_req(
 static ib_api_status_t
 __save_user_req(
        IN                              kcep_t* const                           p_cep,
-       IN              const   ib_cm_req_t* const                      p_cm_req,
+       IN              const   iba_cm_req* const                       p_cm_req,
+       IN                              uint8_t                                         rnr_nak_timeout,
                OUT                     cep_agent_t** const                     pp_port_cep )
 {
        cep_agent_t             *p_port_cep;
@@ -4525,40 +4556,12 @@ __save_user_req(
                return IB_INVALID_SETTING;
        }

-       p_cep->sid = p_cm_req->svc_id;
-
+       p_cep->sid = p_cm_req->service_id;
        p_cep->idx_primary = 0;
-
-       p_cep->p2p = (p_cm_req->pfn_cm_req_cb != NULL);
-
-       if( p_cm_req->p_compare_buffer )
-       {
-               if( !p_cm_req->compare_length ||
-                       (p_cm_req->compare_offset + p_cm_req->compare_length) >
-                       IB_REQ_PDATA_SIZE )
-               {
-                       AL_EXIT( AL_DBG_CM );
-                       return IB_INVALID_SETTING;
-               }
-               p_cep->p_cmp_buf = cl_malloc( p_cm_req->compare_length );
-               if( !p_cep->p_cmp_buf )
-               {
-                       AL_EXIT( AL_DBG_CM );
-                       return IB_INSUFFICIENT_MEMORY;
-               }
-
-               cl_memcpy( p_cep->p_cmp_buf,
-                       p_cm_req->p_compare_buffer, p_cm_req->compare_length );
-
-               p_cep->cmp_len = p_cm_req->compare_length;
-               p_cep->cmp_offset = p_cm_req->compare_offset;
-       }
-       else
-       {
-               p_cep->p_cmp_buf = NULL;
-               p_cep->cmp_len = 0;
-               p_cep->cmp_offset = 0;
-       }
+       p_cep->p2p = FALSE;
+       p_cep->p_cmp_buf = NULL;
+       p_cep->cmp_len = 0;
+       p_cep->cmp_offset = 0;
        p_cep->was_active = TRUE;

        /* Validate the primary path. */
@@ -4571,15 +4574,6 @@ __save_user_req(

        p_cep->av[0].attr.conn.seq_err_retry_cnt = p_cm_req->retry_cnt;

-       /* Make sure the paths will work on the desired QP. */
-       if( p_port_cep->h_ca->obj.p_ci_ca->verbs.guid !=
-               p_cm_req->h_qp->obj.p_ci_ca->verbs.guid )
-       {
-               AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
-                       ("Primary path not realizable on given QP.\n") );
-               return IB_INVALID_SETTING;
-       }
-
        p_cep->local_ca_guid = p_port_cep->h_ca->obj.p_ci_ca->verbs.guid;

        *pp_port_cep = p_port_cep;
@@ -4644,7 +4638,7 @@ __save_user_req(
        p_cep->remote_comm_id = 0;

        /* Cache the local QPN. */
-       p_cep->local_qpn = p_cm_req->h_qp->num;
+       p_cep->local_qpn = p_cm_req->qpn;
        p_cep->remote_ca_guid = 0;
        p_cep->remote_qpn = 0;

@@ -4662,9 +4656,9 @@ __save_user_req(
         */
        p_cep->timewait_time.QuadPart = 0;

-       p_cep->rq_psn = p_cep->local_qpn;
+       p_cep->rq_psn = p_cm_req->starting_psn;

-       p_cep->rnr_nak_timeout = p_cm_req->rnr_nak_timeout;
+       p_cep->rnr_nak_timeout = rnr_nak_timeout;

        AL_EXIT( AL_DBG_CM );
        return IB_SUCCESS;
@@ -4672,11 +4666,12 @@ __save_user_req(


 ib_api_status_t
-al_cep_pre_req(
+kal_cep_pre_req(
        IN                              ib_al_handle_t                          h_al,
        IN                              net32_t                                         cid,
-       IN              const   ib_cm_req_t* const                      p_cm_req,
-               OUT                     ib_qp_mod_t* const                      p_init )
+       IN              const   iba_cm_req* const                       p_cm_req,
+       IN                              uint8_t                                         rnr_nak_timeout,
+       IN      OUT                     ib_qp_mod_t* const                      p_init OPTIONAL )
 {
        ib_api_status_t         status;
        kcep_t                          *p_cep;
@@ -4687,14 +4682,6 @@ al_cep_pre_req(

        CL_ASSERT( h_al );
        CL_ASSERT( p_cm_req );
-       CL_ASSERT( p_init );
-
-       /* TODO: Code P2P support. */
-       if( p_cm_req->pfn_cm_req_cb )
-       {
-               AL_EXIT( AL_DBG_CM );
-               return IB_UNSUPPORTED;
-       }

        KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
        p_cep = __lookup_cep( h_al, cid );
@@ -4713,7 +4700,7 @@ al_cep_pre_req(
                p_cep->p_mad = NULL;
                /* Fall through. */
        case CEP_STATE_IDLE:
-               status = __save_user_req( p_cep, p_cm_req, &p_port_cep );
+               status = __save_user_req( p_cep, p_cm_req, rnr_nak_timeout, &p_port_cep );
                if( status != IB_SUCCESS )
                        break;

@@ -4722,7 +4709,7 @@ al_cep_pre_req(
                if( status != IB_SUCCESS )
                        break;

-               status = __format_req( p_cep, p_cm_req );
+               status = __format_req( p_port_cep, p_cep, p_cm_req );
                if( status != IB_SUCCESS )
                {
                        AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("Invalid pdata length.\n") );
@@ -4732,14 +4719,16 @@ al_cep_pre_req(
                }

                /* Format the INIT qp modify attributes. */
-               p_init->req_state = IB_QPS_INIT;
-               p_init->state.init.primary_port =
-                       p_cep->av[p_cep->idx_primary].attr.port_num;
-               p_init->state.init.qkey = 0;
-               p_init->state.init.pkey_index =
-                       p_cep->av[p_cep->idx_primary].pkey_index;
-               p_init->state.init.access_ctrl = IB_AC_LOCAL_WRITE;
-
+               if( p_init )
+               {
+                       p_init->req_state = IB_QPS_INIT;
+                       p_init->state.init.primary_port =
+                               p_cep->av[p_cep->idx_primary].attr.port_num;
+                       p_init->state.init.qkey = 0;
+                       p_init->state.init.pkey_index =
+                               p_cep->av[p_cep->idx_primary].pkey_index;
+                       p_init->state.init.access_ctrl = IB_AC_LOCAL_WRITE;
+               }
                p_cep->state = CEP_STATE_PRE_REQ;
                break;

@@ -4757,6 +4746,40 @@ al_cep_pre_req(
        return status;
 }

+ib_api_status_t
+al_cep_pre_req(
+       IN                              ib_al_handle_t                          h_al,
+       IN                              net32_t                                         cid,
+       IN              const   ib_cm_req_t* const                      p_cm_req,
+               OUT                     ib_qp_mod_t* const                      p_init )
+{
+       iba_cm_req req;
+
+       RtlZeroMemory(&req, sizeof req);
+       req.service_id = p_cm_req->svc_id;
+
+       req.p_primary_path = p_cm_req->p_primary_path;
+       req.p_alt_path = p_cm_req->p_alt_path;
+
+       req.qpn = p_cm_req->h_qp->num;
+       req.qp_type = p_cm_req->qp_type;
+       req.starting_psn = req.qpn;
+
+       req.p_pdata = (void *) p_cm_req->p_req_pdata;
+       req.pdata_len = p_cm_req->req_length;
+
+       req.max_cm_retries = p_cm_req->max_cm_retries;
+       req.resp_res = p_cm_req->resp_res;
+       req.init_depth = p_cm_req->init_depth;
+       req.remote_resp_timeout = p_cm_req->remote_resp_timeout;
+       req.flow_ctrl = (uint8_t) p_cm_req->flow_ctrl;
+       req.local_resp_timeout = p_cm_req->local_resp_timeout;
+       req.rnr_retry_cnt = p_cm_req->rnr_retry_cnt;
+       req.retry_cnt = p_cm_req->retry_cnt;
+       req.srq = (uint8_t) (p_cm_req->h_qp->h_srq != NULL);
+
+       return kal_cep_pre_req(h_al, cid, &req, p_cm_req->rnr_nak_timeout, p_init);
+}

 ib_api_status_t
 al_cep_send_req(
@@ -4817,31 +4840,32 @@ al_cep_send_req(

 static void
 __save_user_rep(
+       IN                              cep_agent_t* const                      p_port_cep,
        IN                              kcep_t* const                           p_cep,
-       IN              const   ib_cm_rep_t* const                      p_cm_rep )
+       IN              const   iba_cm_rep* const                       p_cm_rep,
+       IN                              uint8_t                                         rnr_nak_timeout )
 {
        AL_ENTER( AL_DBG_CM );

-       /* Cache the local QPN. */
-       p_cep->local_qpn = p_cm_rep->h_qp->num;
-       p_cep->rq_psn = p_cep->local_qpn;
+       p_cep->local_qpn = p_cm_rep->qpn;
+       p_cep->rq_psn = p_cm_rep->starting_psn;
        p_cep->init_depth = p_cm_rep->init_depth;

-       ci_ca_lock_attr( p_cm_rep->h_qp->obj.p_ci_ca );
+       ci_ca_lock_attr( p_port_cep->h_ca->obj.p_ci_ca );
        /* Check the CA's responder resource max and trim if necessary. */
-       if( (p_cm_rep->h_qp->obj.p_ci_ca->p_pnp_attr->max_qp_resp_res <
-               p_cep->resp_res) )
+       if( p_port_cep->h_ca->obj.p_ci_ca->p_pnp_attr->max_qp_resp_res <
+               p_cep->resp_res )
        {
                /*
                 * The CA cannot handle the requested responder resources.
                 * Set the response to the CA's maximum.
                 */
                p_cep->resp_res =
-                       p_cm_rep->h_qp->obj.p_ci_ca->p_pnp_attr->max_qp_resp_res;
+                       p_port_cep->h_ca->obj.p_ci_ca->p_pnp_attr->max_qp_resp_res;
        }
-       ci_ca_unlock_attr( p_cm_rep->h_qp->obj.p_ci_ca );
+       ci_ca_unlock_attr( p_port_cep->h_ca->obj.p_ci_ca );

-       p_cep->rnr_nak_timeout = p_cm_rep->rnr_nak_timeout;
+       p_cep->rnr_nak_timeout = rnr_nak_timeout;

        AL_EXIT( AL_DBG_CM );
 }
@@ -4849,8 +4873,9 @@ __save_user_rep(

 static ib_api_status_t
 __format_rep(
+       IN                              cep_agent_t* const                      p_port_cep,
        IN                              kcep_t* const                           p_cep,
-       IN              const   ib_cm_rep_t* const                      p_cm_rep )
+       IN              const   iba_cm_rep* const                       p_cm_rep )
 {
        ib_api_status_t         status;
        mad_cm_rep_t            *p_rep;
@@ -4898,10 +4923,10 @@ __format_rep(

        p_rep->resp_resources = p_cep->resp_res;

-       ci_ca_lock_attr( p_cm_rep->h_qp->obj.p_ci_ca );
+       ci_ca_lock_attr( p_port_cep->h_ca->obj.p_ci_ca );
        conn_rep_set_target_ack_delay(
-               p_cm_rep->h_qp->obj.p_ci_ca->p_pnp_attr->local_ack_delay, p_rep );
-       ci_ca_unlock_attr( p_cm_rep->h_qp->obj.p_ci_ca );
+               p_port_cep->h_ca->obj.p_ci_ca->p_pnp_attr->local_ack_delay, p_rep );
+       ci_ca_unlock_attr( p_port_cep->h_ca->obj.p_ci_ca );

        p_rep->initiator_depth = p_cep->init_depth;

@@ -4915,7 +4940,7 @@ __format_rep(
        p_rep->local_ca_guid = p_cep->local_ca_guid;

        status = conn_rep_set_pdata(
-               p_cm_rep->p_rep_pdata, p_cm_rep->rep_length, p_rep );
+               p_cm_rep->p_pdata, p_cm_rep->pdata_len, p_rep );

        conn_rep_clr_rsvd_fields( p_rep );

@@ -4925,12 +4950,12 @@ __format_rep(



-ib_api_status_t
+static ib_api_status_t
 __al_cep_pre_rep(
        IN                              kcep_t                                          *p_cep,
-       IN                              void*                                           context,
-       IN              const   ib_cm_rep_t* const                      p_cm_rep,
-               OUT                     ib_qp_mod_t* const                      p_init )
+       IN              const   iba_cm_rep* const                       p_cm_rep,
+       IN                              uint8_t                                         rnr_nak_timeout,
+               OUT                     ib_qp_mod_t* const                      p_init OPTIONAL )
 {
        ib_api_status_t         status;
        cep_agent_t                     *p_port_cep;
@@ -4938,7 +4963,6 @@ __al_cep_pre_rep(
        AL_ENTER( AL_DBG_CM );

        CL_ASSERT( p_cm_rep );
-       CL_ASSERT( p_init );

        switch( p_cep->state )
        {
@@ -4956,9 +4980,9 @@ __al_cep_pre_rep(
                if( status != IB_SUCCESS )
                        break;

-               __save_user_rep( p_cep, p_cm_rep );
+               __save_user_rep( p_port_cep, p_cep, p_cm_rep, rnr_nak_timeout );

-               status = __format_rep( p_cep, p_cm_rep );
+               status = __format_rep( p_port_cep, p_cep, p_cm_rep );
                if( status != IB_SUCCESS )
                {
                        ib_put_mad( p_cep->p_mad );
@@ -4967,16 +4991,16 @@ __al_cep_pre_rep(
                }

                /* Format the INIT qp modify attributes. */
-               p_init->req_state = IB_QPS_INIT;
-               p_init->state.init.primary_port =
-                       p_cep->av[p_cep->idx_primary].attr.port_num;
-               p_init->state.init.qkey = 0;
-               p_init->state.init.pkey_index =
-                       p_cep->av[p_cep->idx_primary].pkey_index;
-               p_init->state.init.access_ctrl = IB_AC_LOCAL_WRITE;
-
-               p_cep->context = context;
-
+               if( p_init )
+               {
+                       p_init->req_state = IB_QPS_INIT;
+                       p_init->state.init.primary_port =
+                               p_cep->av[p_cep->idx_primary].attr.port_num;
+                       p_init->state.init.qkey = 0;
+                       p_init->state.init.pkey_index =
+                               p_cep->av[p_cep->idx_primary].pkey_index;
+                       p_init->state.init.access_ctrl = IB_AC_LOCAL_WRITE;
+               }
                /* Just OR in the PREP bit into the state. */
                p_cep->state |= CEP_STATE_PREP;
                break;
@@ -5001,92 +5025,124 @@ al_cep_pre_rep(
        IN      OUT                     net32_t* const                          p_cid,
                OUT                     ib_qp_mod_t* const                      p_init )
 {
-       ib_api_status_t         status;
        kcep_t                          *p_cep;
+       iba_cm_rep                      rep;
        KLOCK_QUEUE_HANDLE      hdl;
+       ib_api_status_t         status;

-       AL_ENTER( AL_DBG_CM );
-
-       CL_ASSERT( h_al );
-       CL_ASSERT( p_cm_rep );
-       CL_ASSERT( p_init );
+       RtlZeroMemory(&rep, sizeof rep);
+       rep.qpn = p_cm_rep->h_qp->num;
+       rep.starting_psn = rep.qpn;
+
+       rep.p_pdata = (void *) p_cm_rep->p_rep_pdata;
+       rep.pdata_len = p_cm_rep->rep_length;
+
+       rep.failover_accepted = p_cm_rep->failover_accepted;
+       rep.init_depth = p_cm_rep->init_depth;
+       rep.flow_ctrl = (uint8_t) p_cm_rep->flow_ctrl;
+       rep.rnr_retry_cnt = p_cm_rep->rnr_retry_cnt;
+       rep.srq = (uint8_t) (p_cm_rep->h_qp->h_srq != NULL);

        KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
-       if( *p_cid != AL_INVALID_CID )
-       {
-               KeReleaseInStackQueuedSpinLock( &hdl );
-               AL_EXIT( AL_DBG_CM );
-               return IB_RESOURCE_BUSY;
-       }
-
        p_cep = __lookup_cep( h_al, cid );
-       if( !p_cep )
+       if (!p_cep )
        {
-               KeReleaseInStackQueuedSpinLock( &hdl );
-               AL_EXIT( AL_DBG_CM );
-               return IB_INVALID_HANDLE;
+               status = IB_INVALID_HANDLE;
+               goto out;
        }

-       status = __al_cep_pre_rep( p_cep, context, p_cm_rep, p_init );
-
-       if( status == IB_SUCCESS )
+       rep.resp_res = p_cep->resp_res;
+       status = __al_cep_pre_rep( p_cep, &rep, p_cm_rep->rnr_nak_timeout, p_init );
+       if ( status == IB_SUCCESS )
        {
+               p_cep->context = context;
                p_cep->pfn_destroy_cb = pfn_destroy_cb;
                *p_cid = cid;
        }

+out:
        KeReleaseInStackQueuedSpinLock( &hdl );
-       AL_EXIT( AL_DBG_CM );
        return status;
 }


 ib_api_status_t
-al_cep_pre_rep_ex(
+kal_cep_config_pre_rep_copy_cid(
        IN                              ib_al_handle_t                          h_al,
        IN                              net32_t                                         cid,
        IN                              al_pfn_cep_cb_t                         pfn_cb,
        IN                              void*                                           context,
        IN                              ib_pfn_destroy_cb_t                     pfn_destroy_cb,
-       IN              const   ib_cm_rep_t* const                      p_cm_rep,
+       IN              const   iba_cm_rep* const                       p_cm_rep,
+       IN                              uint8_t                                         rnr_nak_timeout,
        IN      OUT                     net32_t* const                          p_cid,
                OUT                     ib_qp_mod_t* const                      p_init )
 {
-       ib_api_status_t         status;
        kcep_t                          *p_cep;
        KLOCK_QUEUE_HANDLE      hdl;
-
-       AL_ENTER( AL_DBG_CM );
+       ib_api_status_t         status;

        CL_ASSERT( h_al );
        CL_ASSERT( p_cm_rep );
        CL_ASSERT( p_init );

        KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
-       if( *p_cid != AL_INVALID_CID )
+       if (*p_cid != AL_INVALID_CID)
        {
-               KeReleaseInStackQueuedSpinLock( &hdl );
-               AL_EXIT( AL_DBG_CM );
-               return IB_RESOURCE_BUSY;
+               status = IB_RESOURCE_BUSY;
+               goto out;
        }

        p_cep = __lookup_cep( h_al, cid );
-       if( !p_cep )
+       if (!p_cep )
        {
-               KeReleaseInStackQueuedSpinLock( &hdl );
-               AL_EXIT( AL_DBG_CM );
-               return IB_INVALID_HANDLE;
+               status = IB_INVALID_HANDLE;
+               goto out;
        }

-       status = __al_cep_pre_rep( p_cep, context, p_cm_rep, p_init );
-
-       if( status == IB_SUCCESS )
+       status = __al_cep_pre_rep( p_cep, p_cm_rep, rnr_nak_timeout, p_init );
+       if ( status == IB_SUCCESS )
        {
                p_cep->pfn_cb = pfn_cb;
+               p_cep->context = context;
                p_cep->pfn_destroy_cb = pfn_destroy_cb;
                *p_cid = cid;
        }

+out:
+       KeReleaseInStackQueuedSpinLock( &hdl );
+       return status;
+}
+
+
+ib_api_status_t
+kal_cep_pre_rep(
+       IN                              ib_al_handle_t                          h_al,
+       IN                              net32_t                                         cid,
+       IN              const   iba_cm_rep* const                       p_cm_rep,
+       IN                              uint8_t                                         rnr_nak_timeout,
+               OUT                     ib_qp_mod_t* const                      p_init OPTIONAL )
+{
+       ib_api_status_t         status;
+       kcep_t                          *p_cep;
+       KLOCK_QUEUE_HANDLE      hdl;
+
+       AL_ENTER( AL_DBG_CM );
+
+       CL_ASSERT( h_al );
+       CL_ASSERT( p_cm_rep );
+
+       KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
+       p_cep = __lookup_cep( h_al, cid );
+       if( !p_cep )
+       {
+               status = IB_INVALID_HANDLE;
+               goto out;
+       }
+
+       status = __al_cep_pre_rep( p_cep, p_cm_rep, rnr_nak_timeout, p_init );
+
+out:
        KeReleaseInStackQueuedSpinLock( &hdl );
        AL_EXIT( AL_DBG_CM );
        return status;
@@ -5110,9 +5166,8 @@ al_cep_send_rep(
        p_cep = __lookup_cep( h_al, cid );
        if( !p_cep )
        {
-               KeReleaseInStackQueuedSpinLock( &hdl );
-               AL_EXIT( AL_DBG_CM );
-               return IB_INVALID_HANDLE;
+               status = IB_INVALID_HANDLE;
+               goto out;
        }

        switch( p_cep->state )
@@ -5123,7 +5178,9 @@ al_cep_send_rep(
                p_port_cep = __get_cep_agent( p_cep );
                if( !p_port_cep )
                {
+                       // Why call ib_put_mad() here but not below?
                        ib_put_mad( p_cep->p_mad );
+                       // Why call __remove_cep() below but not here?
                        p_cep->state = CEP_STATE_IDLE;
                        status = IB_INSUFFICIENT_RESOURCES;
                }
@@ -5148,6 +5205,7 @@ al_cep_send_rep(
                        ("Invalid state: %d\n", p_cep->state) );
                status = IB_INVALID_STATE;
        }
+out:
        KeReleaseInStackQueuedSpinLock( &hdl );
        AL_EXIT( AL_DBG_CM );
        return status;
@@ -5975,6 +6033,263 @@ al_cep_established(
        return status;
 }

+static void
+__format_path(ib_path_rec_t *p_path, req_path_info_t *p_info,
+                         ib_net16_t pkey, uint8_t mtu)
+{
+       p_path->resv0 = 0;
+       p_path->dgid = p_info->local_gid;
+       p_path->sgid = p_info->remote_gid;
+       p_path->dlid = p_info->local_lid;
+       p_path->slid = p_info->remote_lid;
+       ib_path_rec_set_hop_flow_raw(p_path, p_info->hop_limit,
+                                                                conn_req_path_get_flow_lbl(p_info), 0);
+       p_path->tclass = p_info->traffic_class;
+       p_path->num_path = 0;
+       p_path->pkey = pkey;
+       p_path->sl = conn_req_path_get_svc_lvl(p_info);
+       p_path->mtu = mtu;
+       p_path->rate = conn_req_path_get_pkt_rate(p_info);
+       p_path->pkt_life = conn_req_path_get_lcl_ack_timeout(p_info);
+       p_path->preference = 0;
+       p_path->resv1 = 0;
+       p_path->resv2 = 0;
+}
+
+static void
+__format_event_req(kcep_t *p_cep, mad_cm_req_t *p_mad, iba_cm_req_event *p_req)
+{
+       p_req->local_ca_guid = p_cep->local_ca_guid;
+       p_req->remote_ca_guid = p_cep->remote_ca_guid;
+       p_req->pkey_index = p_cep->av[0].pkey_index;
+       p_req->port_num = p_cep->av[0].attr.port_num;
+       p_req->req.service_id = p_mad->sid;
+
+       p_req->req.qpn = conn_req_get_lcl_qpn(p_mad);
+       p_req->req.qp_type = conn_req_get_qp_type(p_mad);
+       p_req->req.starting_psn = conn_req_get_starting_psn(p_mad);
+
+       p_req->req.p_pdata = p_mad->pdata;
+       p_req->req.pdata_len = IB_REQ_PDATA_SIZE;
+
+       p_req->req.max_cm_retries = conn_req_get_max_cm_retries(p_mad);
+       p_req->req.resp_res = conn_req_get_init_depth(p_mad);
+       p_req->req.init_depth = conn_req_get_resp_res(p_mad);
+       p_req->req.remote_resp_timeout = conn_req_get_resp_timeout(p_mad);
+       p_req->req.flow_ctrl = (uint8_t) conn_req_get_flow_ctrl(p_mad);
+       p_req->req.local_resp_timeout = conn_req_get_lcl_resp_timeout(p_mad);
+       p_req->req.rnr_retry_cnt = conn_req_get_rnr_retry_cnt(p_mad);
+       p_req->req.retry_cnt = conn_req_get_retry_cnt(p_mad);
+       p_req->req.srq = 0; // TODO: fix mad_cm_req_t
+
+       // We can re-use the MAD buffer if we're careful to read out the data
+       // that we need before it's overwritten.
+       p_req->req.p_primary_path = (ib_path_rec_t *) p_mad;
+       __format_path(p_req->req.p_primary_path, &p_mad->primary_path,
+                                 p_mad->pkey, conn_req_get_mtu(p_mad));
+
+       if (p_mad->alternate_path.remote_lid != 0) {
+               p_req->req.p_alt_path = p_req->req.p_primary_path + 1;
+               __format_path(p_req->req.p_alt_path, &p_mad->alternate_path,
+                                         p_req->req.p_primary_path->pkey,
+                                         p_req->req.p_primary_path->mtu);
+       } else {
+               p_req->req.p_alt_path = NULL;
+       }
+}
+
+static void
+__format_event_rep(mad_cm_rep_t *p_mad, iba_cm_rep_event *p_rep)
+{
+       p_rep->ca_guid = p_mad->local_ca_guid;
+       p_rep->target_ack_delay = conn_rep_get_target_ack_delay(p_mad);
+       p_rep->rep.qpn = conn_rep_get_lcl_qpn(p_mad);
+       p_rep->rep.starting_psn = conn_rep_get_starting_psn(p_mad);
+
+       p_rep->rep.p_pdata = p_mad->pdata;
+       p_rep->rep.pdata_len = IB_REP_PDATA_SIZE;
+
+       p_rep->rep.failover_accepted = conn_rep_get_failover(p_mad);
+       p_rep->rep.resp_res = p_mad->initiator_depth;
+       p_rep->rep.init_depth = p_mad->resp_resources;
+       p_rep->rep.flow_ctrl = (uint8_t) conn_rep_get_e2e_flow_ctl(p_mad);
+       p_rep->rep.rnr_retry_cnt = conn_rep_get_rnr_retry_cnt(p_mad);
+}
+
+static void
+__format_event_rej(mad_cm_rej_t *p_mad, iba_cm_rej_event *p_rej)
+{
+       p_rej->ari = p_mad->ari;
+       p_rej->p_pdata = p_mad->pdata;
+       p_rej->reason = p_mad->reason;
+       p_rej->ari_length = conn_rej_get_ari_len(p_mad);
+       p_rej->pdata_len = IB_MRA_PDATA_SIZE;
+}
+
+static void
+__format_event_mra(mad_cm_mra_t *p_mad, iba_cm_mra_event *p_mra)
+{
+       p_mra->p_pdata = p_mad->pdata;
+       p_mra->pdata_len = IB_MRA_PDATA_SIZE;
+       p_mra->service_timeout = conn_mra_get_svc_timeout(p_mad);
+}
+
+static void
+__format_event_pdata(kcep_t *p_cep, iba_cm_pdata *p_pdata)
+{
+       p_pdata->p_pdata = p_cep->pdata;
+       p_pdata->pdata_len = p_cep->psize;
+}
+
+/*
+ * Called after polling a MAD from a CEP to parse the received CM message
+ * into readable event data.
+ */
+void
+kal_cep_format_event(
+       IN                              ib_al_handle_t                          h_al,
+       IN                              net32_t                                         cid,
+       IN                              ib_mad_element_t                        *p_mad,
+       IN      OUT                     iba_cm_event                            *p_event)
+{
+       KLOCK_QUEUE_HANDLE      hdl;
+       kcep_t                          *p_cep;
+
+       KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
+       p_cep = __lookup_cep( h_al, cid );
+       KeReleaseInStackQueuedSpinLock( &hdl );
+
+       switch (p_mad->p_mad_buf->attr_id) {
+       case CM_REQ_ATTR_ID:
+               if (p_mad->status == IB_SUCCESS) {
+                       p_event->type = iba_cm_req_received;
+                       __format_event_req(p_cep, (mad_cm_req_t*) p_mad->p_mad_buf, &p_event->data.req);
+               } else {
+                       p_event->type = iba_cm_req_error;
+               }
+               break;
+       case CM_REP_ATTR_ID:
+               if (p_mad->status == IB_SUCCESS) {
+                       p_event->type = iba_cm_rep_received;
+                       __format_event_rep((mad_cm_rep_t*) p_mad->p_mad_buf, &p_event->data.rep);
+               } else {
+                       p_event->type = iba_cm_rep_error;
+               }
+               break;
+       case CM_RTU_ATTR_ID:
+               p_event->type = iba_cm_rtu_received;
+               __format_event_pdata(p_cep, &p_event->data.rtu);
+               break;
+       case CM_DREQ_ATTR_ID:
+               if (p_mad->status == IB_SUCCESS) {
+                       p_event->type = iba_cm_dreq_received;
+                       __format_event_pdata(p_cep, &p_event->data.dreq);
+               } else {
+                       p_event->type = iba_cm_dreq_error;
+               }
+               break;
+       case CM_DREP_ATTR_ID:
+               p_event->type = iba_cm_drep_received;
+               __format_event_pdata(p_cep, &p_event->data.drep);
+               break;
+       case CM_REJ_ATTR_ID:
+               p_event->type = iba_cm_rej_received;
+               __format_event_rej((mad_cm_rej_t*) p_mad->p_mad_buf, &p_event->data.rej);
+               break;
+       case CM_MRA_ATTR_ID:
+               p_event->type = iba_cm_mra_received;
+               __format_event_mra((mad_cm_mra_t*) p_mad->p_mad_buf, &p_event->data.mra);
+               break;
+       case CM_LAP_ATTR_ID:
+               if (p_mad->status == IB_SUCCESS) {
+                       p_event->type = iba_cm_lap_received;
+                       // TODO: format lap event
+               } else {
+                       p_event->type = iba_cm_lap_error;
+               }
+               break;
+       case CM_APR_ATTR_ID:
+               p_event->type = iba_cm_apr_received;;
+               // TODO: format apr event
+               break;
+       case CM_SIDR_REQ_ATTR_ID:
+               if (p_mad->status == IB_SUCCESS) {
+                       p_event->type = iba_cm_sidr_req_received;
+                       // TODO: format sidr req event
+               } else {
+                       p_event->type = iba_cm_sidr_req_error;
+               }
+               break;
+       case CM_SIDR_REP_ATTR_ID:
+               p_event->type = iba_cm_sidr_rep_received;
+               // TODO: format sidr rep event
+               break;
+       default:
+               CL_ASSERT(0);
+       }
+}
+
+
+ib_api_status_t
+al_cep_get_init_attr(
+       IN                              ib_al_handle_t                          h_al,
+       IN                              net32_t                                         cid,
+               OUT                     ib_qp_mod_t* const                      p_init )
+{
+       ib_api_status_t         status;
+       kcep_t                          *p_cep;
+       KLOCK_QUEUE_HANDLE      hdl;
+
+       AL_ENTER( AL_DBG_CM );
+
+       KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
+       p_cep = __lookup_cep( h_al, cid );
+       if( !p_cep )
+       {
+               status = IB_INVALID_HANDLE;
+               goto out;
+       }
+
+       switch( p_cep->state )
+       {
+       case CEP_STATE_PRE_REQ:
+       case CEP_STATE_REQ_RCVD:
+       case CEP_STATE_PRE_REP:
+       case CEP_STATE_REQ_SENT:
+       case CEP_STATE_REQ_MRA_RCVD:
+       case CEP_STATE_REQ_MRA_SENT:
+       case CEP_STATE_PRE_REP_MRA_SENT:
+       case CEP_STATE_REP_RCVD:
+       case CEP_STATE_REP_SENT:
+       case CEP_STATE_REP_MRA_RCVD:
+       case CEP_STATE_REP_MRA_SENT:
+       case CEP_STATE_ESTABLISHED:
+               /* Format the INIT qp modify attributes. */
+               cl_memclr(p_init, sizeof(ib_qp_mod_t));
+               p_init->req_state = IB_QPS_INIT;
+               p_init->state.init.primary_port =
+                       p_cep->av[p_cep->idx_primary].attr.port_num;
+               p_init->state.init.pkey_index =
+                       p_cep->av[p_cep->idx_primary].pkey_index;
+               p_init->state.init.access_ctrl = IB_AC_LOCAL_WRITE;
+               if ( p_cep->resp_res )
+               {
+                       p_init->state.init.access_ctrl |= IB_AC_RDMA_READ |
+                                                                                         IB_AC_RDMA_WRITE |
+                                                                                         IB_AC_ATOMIC;
+               }
+               status = IB_SUCCESS;
+               break;
+       default:
+               status = IB_INVALID_STATE;
+               break;
+       }
+
+out:
+       KeReleaseInStackQueuedSpinLock( &hdl );
+       AL_EXIT( AL_DBG_CM );
+       return status;
+}

 ib_api_status_t
 al_cep_get_rtr_attr(
@@ -6002,6 +6317,8 @@ al_cep_get_rtr_attr(

        switch( p_cep->state )
        {
+       case CEP_STATE_REQ_RCVD:
+       case CEP_STATE_REQ_MRA_SENT:
        case CEP_STATE_PRE_REP:
        case CEP_STATE_PRE_REP_MRA_SENT:
        case CEP_STATE_REP_SENT:
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/core/al/kernel/al_ndi_cm.c branches\winverbs/core/al/kernel/al_ndi_cm.c
--- trunk/core/al/kernel/al_ndi_cm.c    2008-10-29 11:23:54.390625000 -0700
+++ branches\winverbs/core/al/kernel/al_ndi_cm.c        2009-01-23 15:32:58.439471700 -0800
@@ -981,6 +981,7 @@ __ndi_send_req(
        NTSTATUS nt_status;
        ib_cm_req_t cm_req;
        ib_qp_mod_t qp_mod;
+       al_conn_qp_t *p_qp;

        AL_ENTER( AL_DBG_NDI );

@@ -995,19 +996,28 @@ __ndi_send_req(
        }

        /* Get a CEP and bind it to the QP. */
-       status = al_create_cep(
-               qp_get_al( h_qp ), __ndi_cm_handler, h_qp, deref_al_obj,
-               &((al_conn_qp_t*)h_qp)->cid );
+       p_qp = (al_conn_qp_t*)h_qp;
+       cl_spinlock_acquire( &h_qp->obj.lock );
+       if( h_qp->obj.state != CL_DESTROYING && p_qp->cid == AL_INVALID_CID )
+       {
+               status = al_create_cep( qp_get_al( h_qp ), __ndi_cm_handler,
+                                                               &h_qp->obj, deref_al_obj, &p_qp->cid );
+       }
+       else
+       {
+               status = IB_RESOURCE_BUSY;
+       }
+       cl_spinlock_release( &h_qp->obj.lock );
        if( status != IB_SUCCESS )
        {
                h_qp->p_irp_queue->state = NDI_CM_IDLE;
                AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
                        ("al_create_cep returned %s.\n", ib_get_err_str( status )) );
-               return STATUS_INSUFFICIENT_RESOURCES;
+               return ib_to_ntstatus( status );
        }
        AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
                ("Created Active CEP with cid %d, h_al %p, context %p\n",
-               ((al_conn_qp_t*)h_qp)->cid, qp_get_al( h_qp ), h_qp ) );
+               p_qp->cid, qp_get_al( h_qp ), h_qp ) );

        ref_al_obj( &h_qp->obj ); /* Take CEP reference. */

@@ -1015,8 +1025,7 @@ __ndi_send_req(
        __ndi_fill_cm_req( h_qp, p_req, p_path_rec, &cm_req );

        /* prepare CEP for connection */
-       status = al_cep_pre_req( qp_get_al( h_qp ),
-               ((al_conn_qp_t*)h_qp)->cid, &cm_req, &qp_mod );
+       status = al_cep_pre_req( qp_get_al( h_qp ), p_qp->cid, &cm_req, &qp_mod );
        if( status != STATUS_SUCCESS )
        {
                AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
@@ -1025,7 +1034,7 @@ __ndi_send_req(
        }

        /* send CM REQ */
-       status = al_cep_send_req( qp_get_al( h_qp ), ((al_conn_qp_t*)h_qp)->cid );
+       status = al_cep_send_req( qp_get_al( h_qp ), p_qp->cid );
        if( status != IB_SUCCESS )
        {
                AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
@@ -1038,7 +1047,7 @@ __ndi_send_req(
        return STATUS_SUCCESS;

 error:
-       al_destroy_cep( qp_get_al( h_qp ), &((al_conn_qp_t*)h_qp)->cid, TRUE );
+       al_destroy_cep( qp_get_al( h_qp ), &p_qp->cid, TRUE );

        switch( status )
        {
@@ -1469,24 +1478,20 @@ static void
 __ndi_fill_cm_rep(
        IN              ib_qp_handle_t  const                           h_qp,
        IN              ual_ndi_rep_cm_ioctl_in_t                       *p_rep,
-               OUT     ib_cm_rep_t                                                     *p_cm_rep)
+               OUT     iba_cm_rep                                                      *p_cm_rep)
 {
        AL_ENTER( AL_DBG_NDI );

-       memset( p_cm_rep, 0, sizeof(ib_cm_rep_t) );
+       memset( p_cm_rep, 0, sizeof(*p_cm_rep) );

-       p_cm_rep->p_rep_pdata = p_rep->pdata;
-       p_cm_rep->rep_length = sizeof(p_rep->pdata);
+       p_cm_rep->p_pdata = p_rep->pdata;
+       p_cm_rep->pdata_len = sizeof(p_rep->pdata);

-       p_cm_rep->qp_type = IB_QPT_RELIABLE_CONN;
-       p_cm_rep->h_qp = h_qp;
+       p_cm_rep->qpn = h_qp->num;

-       p_cm_rep->access_ctrl = IB_AC_RDMA_READ | IB_AC_RDMA_WRITE | IB_AC_LOCAL_WRITE;
        p_cm_rep->init_depth = p_rep->init_depth;
-       p_cm_rep->target_ack_delay = 10;
        p_cm_rep->failover_accepted = IB_FAILOVER_ACCEPT_UNSUPPORTED;
        p_cm_rep->flow_ctrl = TRUE;     /* HCAs must support end-to-end flow control. */
-       p_cm_rep->rnr_nak_timeout = QP_ATTRIB_RNR_NAK_TIMEOUT;
        p_cm_rep->rnr_retry_cnt = QP_ATTRIB_RNR_RETRY;

        AL_EXIT( AL_DBG_NDI );
@@ -1499,7 +1504,7 @@ __ndi_send_rep(
        IN              PIRP                                                            p_irp )
 {
        IO_STACK_LOCATION       *p_io_stack;
-       ib_cm_rep_t cm_rep;
+       iba_cm_rep cm_rep;
        ib_qp_mod_t qp_mod;
        ib_api_status_t status;
        ual_ndi_rep_cm_ioctl_in_t *p_rep =
@@ -1528,9 +1533,9 @@ __ndi_send_rep(
        ref_al_obj( &h_qp->obj ); /* Take CEP reference. */

        /* prepare Passive CEP for connection */
-       status = al_cep_pre_rep_ex(
-               qp_get_al( h_qp ), p_rep->cid, __ndi_cm_handler, h_qp, deref_al_obj,
-               &cm_rep, &((al_conn_qp_t*)h_qp)->cid, &qp_mod );
+       status = kal_cep_config_pre_rep_copy_cid(
+               qp_get_al( h_qp ), p_rep->cid, __ndi_cm_handler, &h_qp->obj, deref_al_obj,
+               &cm_rep, QP_ATTRIB_RNR_NAK_TIMEOUT, &((al_conn_qp_t*)h_qp)->cid, &qp_mod);
        if( status != IB_SUCCESS )
        {
                IoFreeWorkItem( p_irp->Tail.Overlay.DriverContext[1] );
@@ -1539,7 +1544,7 @@ __ndi_send_rep(
                al_destroy_cep( qp_get_al( h_qp ), &p_rep->cid, FALSE );
                deref_al_obj( &h_qp->obj ); /* Release CEP reference. */
                AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
-                       ("al_cep_pre_rep_ex returned %s.\n", ib_get_err_str( status )) );
+                       ("kal_cep_config_pre_rep_copy_cid returned %s.\n", ib_get_err_str( status )) );
                switch (status)
                {
                        case IB_INVALID_HANDLE:
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/core/al/kernel/SOURCES branches\winverbs/core/al/kernel/SOURCES
--- trunk/core/al/kernel/SOURCES        2008-07-23 12:34:49.203500000 -0700
+++ branches\winverbs/core/al/kernel/SOURCES    2008-11-12 14:37:18.966875000 -0800
@@ -13,6 +13,7 @@ ENABLE_EVENT_TRACING=1

 SOURCES= ibal.rc                       \
        al_ci_ca.c                              \
+       al_cm.c                                 \
        al_cm_cep.c                             \
        al_dev.c                                \
        al_ioc_pnp.c                    \
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/core/bus/kernel/bus_pnp.c branches\winverbs/core/bus/kernel/bus_pnp.c
--- trunk/core/bus/kernel/bus_pnp.c     2008-12-17 11:06:45.664250000 -0800
+++ branches\winverbs/core/bus/kernel/bus_pnp.c 2009-01-14 00:08:23.171875000 -0800
@@ -45,11 +45,14 @@
 #include "complib/cl_memory.h"
 #include <initguid.h>
 #include "iba/ib_ci_ifc.h"
+#include "iba/ib_cm_ifc.h"
+#include "al_cm_cep.h"


 /* Interface names are generated by IoRegisterDeviceInterface. */
 static UNICODE_STRING  al_ifc_name;
 static UNICODE_STRING  ci_ifc_name;
+static UNICODE_STRING  cm_ifc_name;

 KEVENT                                 g_ControlEvent;
 ULONG                                  g_bfi_InstanceCount;
@@ -102,6 +105,11 @@ __query_ci_ifc(
        IN                              IO_STACK_LOCATION* const        p_io_stack );

 static NTSTATUS
+__query_cm_ifc(
+       IN                              DEVICE_OBJECT* const            p_dev_obj,
+       IN                              IO_STACK_LOCATION* const        p_io_stack );
+
+static NTSTATUS
 fdo_query_interface(
        IN                              DEVICE_OBJECT* const            p_dev_obj,
        IN                              IRP* const                                      p_irp,
@@ -130,6 +138,7 @@ __fdo_set_power(
 #pragma alloc_text (PAGE, fdo_query_bus_relations)
 #pragma alloc_text (PAGE, __query_al_ifc)
 #pragma alloc_text (PAGE, __query_ci_ifc)
+#pragma alloc_text (PAGE, __query_cm_ifc)
 #pragma alloc_text (PAGE, __get_relations)
 #pragma alloc_text (PAGE, fdo_query_interface)
 #pragma alloc_text (PAGE_PNP, __fdo_query_power)
@@ -211,16 +220,15 @@ bus_add_device(
                {
                        BUS_PRINT( BUS_DBG_ERROR,
                                ("Failed to create ControlDeviceObject, status %x.\n",status) );
-                       goto bail;
+                       goto err1;
                }
                IoDeleteSymbolicLink( &dos_name );
                status = IoCreateSymbolicLink( &dos_name, &dev_name );
                if( !NT_SUCCESS(status) )
                {
-                       IoDeleteDevice( p_dev_obj );
                        BUS_PRINT( BUS_DBG_ERROR,
                                ("Failed to create symlink for dos name.\n") );
-                       goto bail;
+                       goto err2;
                }
        }
        else {
@@ -231,7 +239,7 @@ bus_add_device(
                {
                        BUS_PRINT( BUS_DBG_ERROR,
                                ("Failed to create bus root FDO device.\n") );
-                       goto bail;
+                       goto err1;
                }
        }

@@ -242,10 +250,9 @@ bus_add_device(
        p_next_do = IoAttachDeviceToDeviceStack( p_dev_obj, p_pdo );
        if( !p_next_do )
        {
-               IoDeleteDevice( p_dev_obj );
                BUS_PRINT( BUS_DBG_ERROR, ("IoAttachToDeviceStack failed.\n") );
                status = STATUS_NO_SUCH_DEVICE;
-               goto bail;
+               goto err2;
        }

        cl_init_pnp_po_ext( p_dev_obj, p_next_do, p_pdo, bus_globals.dbg_lvl,
@@ -265,13 +272,11 @@ bus_add_device(
                                                                                &al_ifc_name );
        if( !NT_SUCCESS( status ) )
        {
-               IoDetachDevice( p_ext->cl_ext.p_next_do );
-               IoDeleteDevice( p_dev_obj );
                BUS_PRINT( BUS_DBG_ERROR,
                        ("IoRegisterDeviceInterface for upper interface returned %08x\n",
                        status) );
                status = STATUS_NO_SUCH_DEVICE;
-               goto bail;
+               goto err3;
        }

        /* Register the lower (CI) interface (the one used by HCA VPDs). */
@@ -279,13 +284,22 @@ bus_add_device(
                                                                                &ci_ifc_name );
        if( !NT_SUCCESS( status ) )
        {
-               IoDetachDevice( p_ext->cl_ext.p_next_do );
-               IoDeleteDevice( p_dev_obj );
                BUS_PRINT( BUS_DBG_ERROR,
                        ("IoRegisterDeviceInterface for lower interface returned %08x\n",
                        status) );
                status = STATUS_NO_SUCH_DEVICE;
-               goto bail;
+               goto err3;
+       }
+
+       status = IoRegisterDeviceInterface( p_pdo, &GUID_INFINIBAND_INTERFACE_CM, NULL,
+                                                                               &cm_ifc_name );
+       if( !NT_SUCCESS( status ) )
+       {
+               BUS_PRINT( BUS_DBG_ERROR,
+                       ("IoRegisterDeviceInterface for cm interface returned %08x\n",
+                       status) );
+               status = STATUS_NO_SUCH_DEVICE;
+               goto err3;
        }

 adxit:
@@ -294,7 +308,11 @@ adxit:
        BUS_EXIT( BUS_DBG_PNP );
        return STATUS_SUCCESS;

-bail:
+err3:
+       IoDetachDevice( p_ext->cl_ext.p_next_do );
+err2:
+       IoDeleteDevice( p_dev_obj );
+err1:
        BUS_PRINT( BUS_DBG_PNP, ("%s exit status 0x%x\n", p_bfi->whoami,status) );
        ic = free_bfi(p_bfi);
        /* if last Bus filter, then cleanup */
@@ -374,6 +392,9 @@ fdo_start(

                status = IoSetDeviceInterfaceState( &ci_ifc_name, TRUE );
                ASSERT( NT_SUCCESS( status ) );
+
+               status = IoSetDeviceInterfaceState( &cm_ifc_name, TRUE );
+               ASSERT( NT_SUCCESS( status ) );
        }

        BUS_PRINT(BUS_DBG_PNP,
@@ -490,8 +511,11 @@ fdo_release_resources(
        ASSERT( NT_SUCCESS( status ) );
        status = IoSetDeviceInterfaceState( &ci_ifc_name, FALSE );
        ASSERT( NT_SUCCESS( status ) );
+       status = IoSetDeviceInterfaceState( &cm_ifc_name, FALSE );
+       ASSERT( NT_SUCCESS( status ) );

        /* Release the memory allocated for the interface symbolic names. */
+       RtlFreeUnicodeString( &cm_ifc_name );
        RtlFreeUnicodeString( &ci_ifc_name );
        RtlFreeUnicodeString( &al_ifc_name );

@@ -909,6 +933,47 @@ __query_ci_ifc(


 static NTSTATUS
+__query_cm_ifc(
+       IN                                      DEVICE_OBJECT* const            p_dev_obj,
+       IN                                      IO_STACK_LOCATION* const        p_io_stack )
+{
+       INFINIBAND_INTERFACE_CM *p_ifc;
+
+       BUS_ENTER( BUS_DBG_PNP );
+
+       if( p_io_stack->Parameters.QueryInterface.Version != IbaCmVersion(1, 0) )
+       {
+               BUS_TRACE_EXIT( BUS_DBG_PNP, ("Incorrect interface version (%d)\n",
+                       p_io_stack->Parameters.QueryInterface.Version ) );
+               return STATUS_NOT_SUPPORTED;
+       }
+
+       if( p_io_stack->Parameters.QueryInterface.Size < sizeof(INFINIBAND_INTERFACE_CM) )
+       {
+               BUS_TRACE_EXIT( BUS_DBG_PNP,
+                       ("Buffer too small (%d given, %d required).\n",
+                       p_io_stack->Parameters.QueryInterface.Size, sizeof(INFINIBAND_INTERFACE_CM)) );
+               return STATUS_BUFFER_TOO_SMALL;
+       }
+
+       /* Copy the interface. */
+       p_ifc = (INFINIBAND_INTERFACE_CM*)p_io_stack->Parameters.QueryInterface.Interface;
+
+       p_ifc->InterfaceHeader.Size = sizeof(INFINIBAND_INTERFACE_CM);
+       p_ifc->InterfaceHeader.Version = IbaCmVersion(1, 0);
+       p_ifc->InterfaceHeader.Context = p_dev_obj;
+       p_ifc->InterfaceHeader.InterfaceReference = al_ref_ifc;
+       p_ifc->InterfaceHeader.InterfaceDereference = al_deref_ifc;
+       cm_get_interface(&p_ifc->CM);
+
+       /* take the reference before returning. */
+       al_ref_ifc( p_dev_obj );
+       BUS_EXIT( BUS_DBG_PNP );
+       return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS
 fdo_query_interface(
        IN                                      DEVICE_OBJECT* const    p_dev_obj,
        IN                                      IRP* const                              p_irp,
@@ -934,6 +999,11 @@ fdo_query_interface(
        {
                status = __query_ci_ifc( p_dev_obj, p_io_stack );
        }
+       else if( IsEqualGUID( p_io_stack->Parameters.QueryInterface.InterfaceType,
+               &GUID_INFINIBAND_INTERFACE_CM ) )
+       {
+               status = __query_cm_ifc( p_dev_obj, p_io_stack );
+       }
        else
        {
                status = p_irp->IoStatus.Status;




More information about the ofw mailing list