#ifndef _AL_CM_CEP_H_\r
#define _AL_CM_CEP_H_\r
\r
-\r
#include <iba/ib_al.h>\r
#include "al_common.h"\r
\r
+#ifdef CL_KERNEL\r
+#include <iba/ib_cm_ifc.h>\r
+#endif\r
\r
#define CEP_EVENT_TIMEOUT 0x80000000\r
#define CEP_EVENT_RECV 0x40000000\r
* event notification.\r
*********/\r
\r
+#ifdef CL_KERNEL\r
+ib_api_status_t\r
+kal_cep_alloc(\r
+ IN ib_al_handle_t h_al,\r
+ IN OUT net32_t* const p_cid );\r
+\r
+void\r
+kal_cep_config(\r
+ IN ib_al_handle_t h_al,\r
+ IN net32_t cid,\r
+ IN al_pfn_cep_cb_t pfn_cb,\r
+ IN void* context,\r
+ IN ib_pfn_destroy_cb_t pfn_destroy_cb );\r
+#endif\r
+\r
/* Destruction is asynchronous. */\r
void\r
al_destroy_cep(\r
IN ib_cep_listen_t* const p_listen_info );\r
\r
\r
+#ifdef CL_KERNEL\r
+ib_api_status_t\r
+kal_cep_pre_req(\r
+ IN ib_al_handle_t h_al,\r
+ IN net32_t cid,\r
+ IN const iba_cm_req* const p_cm_req,\r
+ IN uint8_t rnr_nak_timeout,\r
+ IN OUT ib_qp_mod_t* const p_init OPTIONAL );\r
+#endif\r
+\r
ib_api_status_t\r
al_cep_pre_req(\r
IN ib_al_handle_t h_al,\r
IN OUT net32_t* const p_cid,\r
OUT ib_qp_mod_t* const p_init );\r
\r
+#ifdef CL_KERNEL\r
+ib_api_status_t\r
+kal_cep_pre_rep(\r
+ IN ib_al_handle_t h_al,\r
+ IN net32_t cid,\r
+ IN const iba_cm_rep* const p_cm_rep,\r
+ IN uint8_t rnr_nak_timeout,\r
+ IN OUT ib_qp_mod_t* const p_init OPTIONAL );\r
+\r
ib_api_status_t\r
-al_cep_pre_rep_ex(\r
+kal_cep_config_pre_rep_copy_cid(\r
IN ib_al_handle_t h_al,\r
IN net32_t cid,\r
IN al_pfn_cep_cb_t pfn_cb,\r
IN void* context,\r
- IN ib_pfn_destroy_cb_t pfn_destroy_cb OPTIONAL,\r
- IN const ib_cm_rep_t* const p_cm_rep,\r
+ IN ib_pfn_destroy_cb_t pfn_destroy_cb,\r
+ IN const iba_cm_rep* const p_cm_rep,\r
+ IN uint8_t rnr_nak_timeout,\r
IN OUT net32_t* const p_cid,\r
OUT ib_qp_mod_t* const p_init );\r
\r
+void\r
+kal_cep_destroy(\r
+ IN ib_al_handle_t h_al,\r
+ IN net32_t cid );\r
+#endif\r
+\r
ib_api_status_t\r
al_cep_send_rep(\r
IN ib_al_handle_t h_al,\r
IN net32_t cid );\r
\r
+#ifdef CL_KERNEL\r
+void\r
+kal_cep_format_event(\r
+ IN ib_al_handle_t h_al,\r
+ IN net32_t cid,\r
+ IN ib_mad_element_t *p_mad,\r
+ IN OUT iba_cm_event *p_event);\r
+\r
+ib_api_status_t\r
+al_cep_get_init_attr(\r
+ IN ib_al_handle_t h_al,\r
+ IN net32_t cid,\r
+ OUT ib_qp_mod_t* const p_init );\r
+#endif\r
\r
ib_api_status_t\r
al_cep_get_rtr_attr(\r
\r
\r
#ifdef CL_KERNEL\r
+void cm_get_interface(iba_cm_interface *p_ifc);\r
\r
NTSTATUS\r
al_cep_queue_irp(\r
\r
SOURCES= ibal.rc \\r
al_ci_ca.c \\r
+ al_cm.c \\r
al_cm_cep.c \\r
al_dev.c \\r
al_ioc_pnp.c \\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 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
+\r
+#include <iba/ib_cm_ifc.h>\r
+#include "al_cm_cep.h"\r
+#include "al_mgr.h"\r
+#include "al_proxy.h"\r
+#include "al_cm_conn.h"\r
+#include "al_cm_sidr.h"\r
+\r
+typedef struct _iba_cm_id_priv\r
+{\r
+ iba_cm_id id;\r
+ KEVENT destroy_event; \r
+\r
+} iba_cm_id_priv;\r
+\r
+static iba_cm_id*\r
+cm_alloc_id(NTSTATUS (*callback)(iba_cm_id *p_id, iba_cm_event *p_event),\r
+ void *context)\r
+{\r
+ iba_cm_id_priv *id;\r
+\r
+ id = ExAllocatePoolWithTag(NonPagedPool, sizeof(iba_cm_id_priv), 'mcbi');\r
+ if (id == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ KeInitializeEvent(&id->destroy_event, NotificationEvent, FALSE);\r
+ id->id.callback = callback;\r
+ id->id.context = context;\r
+ return &id->id;\r
+}\r
+\r
+static void\r
+cm_free_id(iba_cm_id *id)\r
+{\r
+ ExFreePool(CONTAINING_RECORD(id, iba_cm_id_priv, id));\r
+}\r
+\r
+static void\r
+cm_destroy_handler(void *context)\r
+{\r
+ iba_cm_id_priv *id = context;\r
+ KeSetEvent(&id->destroy_event, 0, FALSE);\r
+}\r
+\r
+static void\r
+cm_cep_handler(const ib_al_handle_t h_al, const net32_t cid)\r
+{\r
+ void *context;\r
+ net32_t new_cid;\r
+ ib_mad_element_t *mad;\r
+ iba_cm_id *id, *listen_id;\r
+ iba_cm_event event;\r
+ NTSTATUS status;\r
+\r
+ while (al_cep_poll(h_al, cid, &context, &new_cid, &mad) == IB_SUCCESS) {\r
+\r
+ if (new_cid == AL_INVALID_CID) {\r
+ id = (iba_cm_id *) context;\r
+ } else {\r
+ listen_id = (iba_cm_id *) context;\r
+\r
+ id = cm_alloc_id(listen_id->callback, listen_id);\r
+ if (id == NULL) {\r
+ kal_cep_destroy(h_al, new_cid);\r
+ ib_put_mad(mad);\r
+ continue;\r
+ }\r
+\r
+ kal_cep_config(h_al, new_cid, cm_cep_handler, id, cm_destroy_handler);\r
+ id->cid = new_cid;\r
+ }\r
+\r
+ kal_cep_format_event(h_al, id->cid, mad, &event);\r
+ status = id->callback(id, &event);\r
+ if (!NT_SUCCESS(status)) {\r
+ kal_cep_config(h_al, new_cid, NULL, NULL, NULL);\r
+ kal_cep_destroy(h_al, id->cid);\r
+ cm_free_id(id);\r
+ }\r
+ ib_put_mad(mad);\r
+ }\r
+}\r
+\r
+static NTSTATUS\r
+cm_create_id(NTSTATUS (*callback)(iba_cm_id *p_id, iba_cm_event *p_event),\r
+ void *context, iba_cm_id **pp_id)\r
+{\r
+ iba_cm_id *id;\r
+ ib_api_status_t ib_status;\r
+\r
+ id = cm_alloc_id(callback, context);\r
+ if (id == NULL) {\r
+ return STATUS_NO_MEMORY;\r
+ }\r
+\r
+ ib_status = kal_cep_alloc(gh_al, &id->cid);\r
+ if (ib_status != IB_SUCCESS) {\r
+ cm_free_id(id);\r
+ return ib_to_ntstatus(ib_status);\r
+ }\r
+\r
+ kal_cep_config(gh_al, id->cid, cm_cep_handler, id, cm_destroy_handler);\r
+ *pp_id = id;\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+static void\r
+cm_destroy_id(iba_cm_id *p_id)\r
+{\r
+ iba_cm_id_priv *id;\r
+\r
+ id = CONTAINING_RECORD(p_id, iba_cm_id_priv, id);\r
+ kal_cep_destroy(gh_al, p_id->cid);\r
+ KeWaitForSingleObject(&id->destroy_event, Executive, KernelMode, FALSE, NULL);\r
+ cm_free_id(p_id);\r
+}\r
+\r
+static NTSTATUS\r
+cm_listen(iba_cm_id *p_id, net64_t service_id, void *p_compare_buf,\r
+ uint8_t compare_len, uint8_t compare_offset)\r
+{\r
+ ib_cep_listen_t info;\r
+ ib_api_status_t ib_status;\r
+\r
+ info.svc_id = service_id;\r
+ info.port_guid = IB_ALL_PORTS;\r
+ info.p_cmp_buf = p_compare_buf;\r
+ info.cmp_len = compare_len;\r
+ info.cmp_offset = compare_offset;\r
+ \r
+ ib_status = al_cep_listen(gh_al, p_id->cid, &info);\r
+ return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_send_req(iba_cm_id *p_id, iba_cm_req *p_req)\r
+{\r
+ ib_api_status_t ib_status;\r
+ \r
+ ib_status = kal_cep_pre_req(gh_al, p_id->cid, p_req, 0, NULL);\r
+ if (ib_status != IB_SUCCESS) {\r
+ return ib_to_ntstatus(ib_status);\r
+ }\r
+\r
+ ib_status = al_cep_send_req(gh_al, p_id->cid);\r
+ return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_send_rep(iba_cm_id *p_id, iba_cm_rep *p_rep)\r
+{\r
+ ib_api_status_t ib_status;\r
+\r
+ ib_status = kal_cep_pre_rep(gh_al, p_id->cid, p_rep, 0, NULL);\r
+ if (ib_status != IB_SUCCESS) {\r
+ return ib_to_ntstatus(ib_status);\r
+ }\r
+\r
+ ib_status = al_cep_send_rep(gh_al, p_id->cid);\r
+ return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_send_rtu(iba_cm_id *p_id, void *p_pdata, uint8_t pdata_len)\r
+{\r
+ ib_api_status_t ib_status;\r
+\r
+ ib_status = al_cep_rtu(gh_al, p_id->cid, p_pdata, pdata_len);\r
+ return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_send_dreq(iba_cm_id *p_id, void *p_pdata, uint8_t pdata_len)\r
+{\r
+ ib_api_status_t ib_status;\r
+\r
+ ib_status = al_cep_dreq(gh_al, p_id->cid, p_pdata, pdata_len);\r
+ return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_send_drep(iba_cm_id *p_id, void *p_pdata, uint8_t pdata_len)\r
+{\r
+ ib_api_status_t ib_status;\r
+\r
+ ib_status = al_cep_drep(gh_al, p_id->cid, p_pdata, pdata_len);\r
+ return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_send_rej(iba_cm_id *p_id, ib_rej_status_t status,\r
+ void *p_ari, uint8_t ari_len,\r
+ void *p_pdata, uint8_t pdata_len)\r
+{\r
+ ib_api_status_t ib_status;\r
+\r
+ ib_status = al_cep_rej(gh_al, p_id->cid, status, p_ari, ari_len,\r
+ p_pdata, pdata_len);\r
+ return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_send_mra(iba_cm_id *p_id, uint8_t service_timeout,\r
+ void *p_pdata, uint8_t pdata_len)\r
+{\r
+ ib_cm_mra_t mra;\r
+ ib_api_status_t ib_status;\r
+\r
+ mra.svc_timeout = service_timeout;\r
+ mra.p_mra_pdata = p_pdata;\r
+ mra.mra_length = pdata_len;\r
+\r
+ ib_status = al_cep_mra(gh_al, p_id->cid, &mra);\r
+ return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_send_lap(iba_cm_id *p_id, iba_cm_lap *p_lap)\r
+{\r
+ ib_cm_lap_t lap;\r
+ ib_api_status_t ib_status;\r
+\r
+ RtlZeroMemory(&lap, sizeof lap);\r
+ lap.p_lap_pdata = p_lap->p_pdata;\r
+ lap.lap_length = p_lap->pdata_len;\r
+ lap.remote_resp_timeout = p_lap->remote_resp_timeout;\r
+ lap.p_alt_path = p_lap->p_alt_path;\r
+\r
+ ib_status = al_cep_lap(gh_al, p_id->cid, &lap);\r
+ return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_send_apr(iba_cm_id *p_id, iba_cm_apr *p_apr)\r
+{\r
+ ib_cm_apr_t apr;\r
+ ib_qp_mod_t attr;\r
+ ib_api_status_t ib_status;\r
+\r
+ RtlZeroMemory(&apr, sizeof apr);\r
+ apr.p_apr_pdata = p_apr->p_pdata;\r
+ apr.apr_length = p_apr->pdata_len;\r
+ apr.apr_status = p_apr->status;\r
+ apr.info_length = p_apr->info_length;\r
+ apr.p_info = p_apr->p_info;\r
+\r
+ ib_status = al_cep_pre_apr(gh_al, p_id->cid, &apr, &attr);\r
+ if (ib_status != IB_SUCCESS) {\r
+ return ib_to_ntstatus(ib_status);\r
+ }\r
+\r
+ ib_status = al_cep_send_apr(gh_al, p_id->cid);\r
+ return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_send_sidr_req(iba_cm_id *p_id, iba_cm_sidr_req *p_req)\r
+{\r
+ UNUSED_PARAM(p_id);\r
+ UNUSED_PARAM(p_req);\r
+\r
+ return STATUS_NOT_SUPPORTED;\r
+}\r
+\r
+static NTSTATUS\r
+cm_send_sidr_rep(iba_cm_id *p_id, iba_cm_sidr_rep *p_rep)\r
+{\r
+ UNUSED_PARAM(p_id);\r
+ UNUSED_PARAM(p_rep);\r
+\r
+ return STATUS_NOT_SUPPORTED;\r
+}\r
+\r
+static NTSTATUS\r
+cm_get_qp_attr(iba_cm_id *p_id, ib_qp_state_t state, ib_qp_mod_t *p_attr)\r
+{\r
+ ib_api_status_t ib_status;\r
+\r
+ switch (state) {\r
+ case IB_QPS_INIT:\r
+ ib_status = al_cep_get_init_attr(gh_al, p_id->cid, p_attr);\r
+ break;\r
+ case IB_QPS_RTR:\r
+ ib_status = al_cep_get_rtr_attr(gh_al, p_id->cid, p_attr);\r
+ break;\r
+ case IB_QPS_RTS:\r
+ ib_status = al_cep_get_rts_attr(gh_al, p_id->cid, p_attr);\r
+ break;\r
+ default:\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+\r
+ return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_migrate(iba_cm_id *p_id)\r
+{\r
+ ib_api_status_t ib_status;\r
+\r
+ ib_status = al_cep_migrate(gh_al, p_id->cid);\r
+ return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_establish(iba_cm_id *p_id)\r
+{\r
+ ib_api_status_t ib_status;\r
+\r
+ ib_status = al_cep_established(gh_al, p_id->cid);\r
+ return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+void cm_get_interface(iba_cm_interface *p_ifc)\r
+{\r
+ p_ifc->create_id = cm_create_id;\r
+ p_ifc->destroy_id = cm_destroy_id;\r
+ p_ifc->listen = cm_listen;\r
+ p_ifc->send_req = cm_send_req;\r
+ p_ifc->send_rep = cm_send_rep;\r
+ p_ifc->send_rtu = cm_send_rtu;\r
+ p_ifc->send_dreq = cm_send_dreq;\r
+ p_ifc->send_drep = cm_send_drep;\r
+ p_ifc->send_rej = cm_send_rej;\r
+ p_ifc->send_mra = cm_send_mra;\r
+ p_ifc->send_lap = cm_send_lap;\r
+ p_ifc->send_apr = cm_send_apr;\r
+ p_ifc->send_sidr_req = cm_send_sidr_req;\r
+ p_ifc->send_sidr_rep = cm_send_sidr_rep;\r
+ p_ifc->get_qp_attr = cm_get_qp_attr;\r
+ p_ifc->migrate = cm_migrate;\r
+ p_ifc->established = cm_establish;\r
+}\r
#include <complib/cl_rbmap.h>\r
#include <complib/cl_qmap.h>\r
#include <complib/cl_spinlock.h>\r
+#include <iba/ib_cm_ifc.h>\r
#include "al_common.h"\r
#include "al_cm_cep.h"\r
#include "al_cm_conn.h"\r
ib_mad_svc_handle_t h_mad_svc;\r
ib_mad_element_t *p_send_mad;\r
\r
- /* Number of outstanding MADs. Delays destruction of CEP destruction. */\r
atomic32_t ref_cnt;\r
\r
/* MAD transaction ID to use when sending MADs. */\r
} mads;\r
\r
/*\r
- * NDI stuff\r
+ * NDI stuff - TODO: manage above core kernel CM code\r
*/\r
\r
/* IRP list head */\r
\r
KeAcquireInStackQueuedSpinLockAtDpcLevel( &gp_cep_mgr->lock, &hdl );\r
\r
- if( conn_req_get_qp_type( p_req ) > IB_QPT_UNRELIABLE_CONN )\r
+ if( conn_req_get_qp_type( p_req ) > IB_QPT_UNRELIABLE_CONN ||\r
+ conn_req_get_lcl_qpn( p_req ) == 0 )\r
{\r
/* Reserved value. Reject. */\r
AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("Invalid transport type received.\n") );\r
return IB_INVALID_STATE;\r
}\r
\r
+ // TODO: Remove - manage above core kernel CM code\r
/* NDI connection request case */\r
if ( p_cep->state == CEP_STATE_LISTEN &&\r
(p_cep->sid & ~0x0ffffffI64) == IB_REQ_CM_RDMA_SID_PREFIX )\r
cl_spinlock_release( &h_al->obj.lock );\r
}\r
\r
+ib_api_status_t\r
+kal_cep_alloc(\r
+ IN ib_al_handle_t h_al,\r
+ IN OUT net32_t* const p_cid )\r
+{\r
+ kcep_t *p_cep;\r
+ KLOCK_QUEUE_HANDLE hdl;\r
+\r
+ KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
+ p_cep = __create_cep();\r
+ KeReleaseInStackQueuedSpinLock( &hdl );\r
+\r
+ if( !p_cep )\r
+ return IB_INSUFFICIENT_MEMORY;\r
+\r
+ __bind_cep(p_cep, h_al, NULL, NULL);\r
+ *p_cid = p_cep->cid;\r
+ return IB_SUCCESS;\r
+}\r
+\r
+void\r
+kal_cep_config(\r
+ IN ib_al_handle_t h_al,\r
+ IN net32_t cid,\r
+ IN al_pfn_cep_cb_t pfn_cb,\r
+ IN void* context,\r
+ IN ib_pfn_destroy_cb_t pfn_destroy_cb )\r
+{\r
+ kcep_t *p_cep;\r
+ KLOCK_QUEUE_HANDLE hdl;\r
+\r
+ KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
+ p_cep = __lookup_cep( h_al, cid );\r
+ CL_ASSERT( p_cep );\r
+\r
+ p_cep->pfn_cb = pfn_cb;\r
+ p_cep->context = context;\r
+ p_cep->pfn_destroy_cb = pfn_destroy_cb;\r
+\r
+ KeReleaseInStackQueuedSpinLock( &hdl );\r
+}\r
\r
static inline void\r
__unbind_cep(\r
sizeof(p_cep->local_ca_guid), NULL, 0 );\r
break;\r
\r
- case CEP_STATE_ESTABLISHED:\r
- case CEP_STATE_LAP_RCVD:\r
case CEP_STATE_LAP_SENT:\r
case CEP_STATE_LAP_MRA_RCVD:\r
+ ib_cancel_mad( p_cep->h_mad_svc, p_cep->p_send_mad );\r
+ /* fall through */\r
+ case CEP_STATE_ESTABLISHED:\r
+ case CEP_STATE_LAP_RCVD:\r
case CEP_STATE_LAP_MRA_SENT:\r
case CEP_STATE_PRE_APR:\r
case CEP_STATE_PRE_APR_MRA_SENT:\r
/* Fall through. */\r
\r
case CEP_STATE_DREQ_SENT:\r
+ ib_cancel_mad( p_cep->h_mad_svc, p_cep->p_send_mad );\r
p_cep->state = CEP_STATE_DREQ_DESTROY;\r
- AL_EXIT( AL_DBG_CM );\r
- return cl_atomic_dec( &p_cep->ref_cnt );\r
+ goto out;\r
\r
case CEP_STATE_DREQ_RCVD:\r
/* Send the DREP. */\r
case CEP_STATE_TIMEWAIT:\r
/* Already in timewait - so all is good. */\r
p_cep->state = CEP_STATE_DESTROY;\r
- AL_EXIT( AL_DBG_CM );\r
- return cl_atomic_dec( &p_cep->ref_cnt );\r
+ goto out;\r
}\r
\r
p_cep->state = CEP_STATE_DESTROY;\r
__insert_timewait( p_cep );\r
\r
+out:\r
AL_EXIT( AL_DBG_CM );\r
return cl_atomic_dec( &p_cep->ref_cnt );\r
}\r
IN ib_pfn_destroy_cb_t pfn_destroy_cb,\r
IN OUT net32_t* const p_cid )\r
{\r
- kcep_t *p_cep;\r
- KLOCK_QUEUE_HANDLE hdl;\r
+ ib_api_status_t status;\r
\r
AL_ENTER( AL_DBG_CM );\r
+ CL_ASSERT( h_al );\r
\r
- CL_ASSERT( p_cid );\r
-\r
- KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
- if( *p_cid != AL_INVALID_CID )\r
+ status = kal_cep_alloc(h_al, p_cid);\r
+ if ( status == IB_SUCCESS )\r
{\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
- return IB_RESOURCE_BUSY;\r
+ kal_cep_config(h_al, *p_cid, pfn_cb, context, pfn_destroy_cb);\r
}\r
- p_cep = __create_cep();\r
- if( !p_cep )\r
- {\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
- AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("Failed to allocate CEP.\n") );\r
- return IB_INSUFFICIENT_MEMORY;\r
- }\r
-\r
- __bind_cep( p_cep, h_al, pfn_cb, context );\r
-\r
- p_cep->pfn_destroy_cb = pfn_destroy_cb;\r
- *p_cid = p_cep->cid;\r
-\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
-\r
- AL_PRINT(TRACE_LEVEL_INFORMATION ,AL_DBG_CM ,\r
- ("Created CEP with cid %d, h_al %p, context %p \n", \r
- p_cep->cid, h_al, p_cep->context ));\r
\r
AL_EXIT( AL_DBG_CM );\r
- return IB_SUCCESS;\r
+ return status;\r
}\r
\r
\r
IN OUT net32_t* const p_cid,\r
IN boolean_t reusable )\r
{\r
- net32_t cid = *p_cid;\r
+ net32_t cid;\r
kcep_t *p_cep;\r
KLOCK_QUEUE_HANDLE hdl;\r
void *context;\r
* will succeed for it.\r
*/\r
KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
+ cid = *p_cid;\r
p_cep = __lookup_cep( h_al, cid );\r
if( !p_cep )\r
{\r
\r
KeReleaseInStackQueuedSpinLock( &hdl );\r
\r
- /*\r
- * Done waiting. Release the reference so the timewait timer callback\r
- * can finish cleaning up.\r
- */\r
if( !ref_cnt && pfn_destroy_cb )\r
pfn_destroy_cb( context );\r
\r
AL_EXIT( AL_DBG_CM );\r
}\r
\r
+void\r
+kal_cep_destroy(\r
+ IN ib_al_handle_t h_al,\r
+ IN net32_t cid )\r
+{\r
+ al_destroy_cep(h_al, &cid, FALSE);\r
+}\r
+\r
\r
ib_api_status_t\r
al_cep_listen(\r
\r
static ib_api_status_t\r
__format_req(\r
+ IN cep_agent_t* const p_port_cep,\r
IN kcep_t* const p_cep,\r
- IN const ib_cm_req_t* const p_cm_req )\r
+ IN const iba_cm_req* const p_cm_req )\r
{\r
ib_api_status_t status;\r
mad_cm_req_t* p_req;\r
\r
p_req = (mad_cm_req_t*)p_cep->p_mad->p_mad_buf;\r
\r
- ci_ca_lock_attr( p_cm_req->h_qp->obj.p_ci_ca );\r
+ ci_ca_lock_attr( p_port_cep->h_ca->obj.p_ci_ca );\r
/*\r
* Store the local CA's ack timeout for use when computing\r
* the local ACK timeout.\r
*/\r
p_cep->local_ack_delay =\r
- p_cm_req->h_qp->obj.p_ci_ca->p_pnp_attr->local_ack_delay;\r
- ci_ca_unlock_attr( p_cm_req->h_qp->obj.p_ci_ca );\r
+ p_port_cep->h_ca->obj.p_ci_ca->p_pnp_attr->local_ack_delay;\r
+ ci_ca_unlock_attr( p_port_cep->h_ca->obj.p_ci_ca );\r
\r
/* Format the primary path. */\r
__format_req_path( p_cm_req->p_primary_path,\r
\r
/* Set the local communication in the REQ. */\r
p_req->local_comm_id = p_cep->local_comm_id;\r
- p_req->sid = p_cm_req->svc_id;\r
- p_req->local_ca_guid = p_cm_req->h_qp->obj.p_ci_ca->verbs.guid;\r
+ p_req->sid = p_cm_req->service_id;\r
+ p_req->local_ca_guid = p_port_cep->h_ca->obj.p_ci_ca->verbs.guid;\r
\r
conn_req_set_lcl_qpn( p_cep->local_qpn, p_req );\r
conn_req_set_resp_res( p_cm_req->resp_res, p_req );\r
conn_req_set_init_depth( p_cm_req->init_depth, p_req );\r
conn_req_set_remote_resp_timeout( p_cm_req->remote_resp_timeout, p_req );\r
- conn_req_set_qp_type( p_cm_req->h_qp->type, p_req );\r
+ conn_req_set_qp_type( p_cm_req->qp_type, p_req );\r
conn_req_set_flow_ctrl( p_cm_req->flow_ctrl, p_req );\r
- conn_req_set_starting_psn( p_cep->rq_psn, p_req );\r
+ conn_req_set_starting_psn( p_cm_req->starting_psn, p_req );\r
\r
conn_req_set_lcl_resp_timeout( p_cm_req->local_resp_timeout, p_req );\r
conn_req_set_retry_cnt( p_cm_req->retry_cnt, p_req );\r
\r
conn_req_set_max_cm_retries( p_cm_req->max_cm_retries, p_req );\r
status = conn_req_set_pdata(\r
- p_cm_req->p_req_pdata, p_cm_req->req_length, p_req );\r
+ p_cm_req->p_pdata, p_cm_req->pdata_len, p_req );\r
\r
conn_req_clr_rsvd_fields( p_req );\r
\r
static ib_api_status_t\r
__save_user_req(\r
IN kcep_t* const p_cep,\r
- IN const ib_cm_req_t* const p_cm_req,\r
+ IN const iba_cm_req* const p_cm_req,\r
+ IN uint8_t rnr_nak_timeout,\r
OUT cep_agent_t** const pp_port_cep )\r
{\r
cep_agent_t *p_port_cep;\r
return IB_INVALID_SETTING;\r
}\r
\r
- p_cep->sid = p_cm_req->svc_id;\r
-\r
+ p_cep->sid = p_cm_req->service_id;\r
p_cep->idx_primary = 0;\r
-\r
- p_cep->p2p = (p_cm_req->pfn_cm_req_cb != NULL);\r
-\r
- if( p_cm_req->p_compare_buffer )\r
- {\r
- if( !p_cm_req->compare_length ||\r
- (p_cm_req->compare_offset + p_cm_req->compare_length) >\r
- IB_REQ_PDATA_SIZE )\r
- {\r
- AL_EXIT( AL_DBG_CM );\r
- return IB_INVALID_SETTING;\r
- }\r
- p_cep->p_cmp_buf = cl_malloc( p_cm_req->compare_length );\r
- if( !p_cep->p_cmp_buf )\r
- {\r
- AL_EXIT( AL_DBG_CM );\r
- return IB_INSUFFICIENT_MEMORY;\r
- }\r
-\r
- cl_memcpy( p_cep->p_cmp_buf,\r
- p_cm_req->p_compare_buffer, p_cm_req->compare_length );\r
-\r
- p_cep->cmp_len = p_cm_req->compare_length;\r
- p_cep->cmp_offset = p_cm_req->compare_offset;\r
- }\r
- else\r
- {\r
- p_cep->p_cmp_buf = NULL;\r
- p_cep->cmp_len = 0;\r
- p_cep->cmp_offset = 0;\r
- }\r
+ p_cep->p2p = FALSE;\r
+ p_cep->p_cmp_buf = NULL;\r
+ p_cep->cmp_len = 0;\r
+ p_cep->cmp_offset = 0;\r
p_cep->was_active = TRUE;\r
\r
/* Validate the primary path. */\r
\r
p_cep->av[0].attr.conn.seq_err_retry_cnt = p_cm_req->retry_cnt;\r
\r
- /* Make sure the paths will work on the desired QP. */\r
- if( p_port_cep->h_ca->obj.p_ci_ca->verbs.guid !=\r
- p_cm_req->h_qp->obj.p_ci_ca->verbs.guid )\r
- {\r
- AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
- ("Primary path not realizable on given QP.\n") );\r
- return IB_INVALID_SETTING;\r
- }\r
-\r
p_cep->local_ca_guid = p_port_cep->h_ca->obj.p_ci_ca->verbs.guid;\r
\r
*pp_port_cep = p_port_cep;\r
p_cep->remote_comm_id = 0;\r
\r
/* Cache the local QPN. */\r
- p_cep->local_qpn = p_cm_req->h_qp->num;\r
+ p_cep->local_qpn = p_cm_req->qpn;\r
p_cep->remote_ca_guid = 0;\r
p_cep->remote_qpn = 0;\r
\r
*/\r
p_cep->timewait_time.QuadPart = 0;\r
\r
- p_cep->rq_psn = p_cep->local_qpn;\r
+ p_cep->rq_psn = p_cm_req->starting_psn;\r
\r
- p_cep->rnr_nak_timeout = p_cm_req->rnr_nak_timeout;\r
+ p_cep->rnr_nak_timeout = rnr_nak_timeout;\r
\r
AL_EXIT( AL_DBG_CM );\r
return IB_SUCCESS;\r
\r
\r
ib_api_status_t\r
-al_cep_pre_req(\r
+kal_cep_pre_req(\r
IN ib_al_handle_t h_al,\r
IN net32_t cid,\r
- IN const ib_cm_req_t* const p_cm_req,\r
- OUT ib_qp_mod_t* const p_init )\r
+ IN const iba_cm_req* const p_cm_req,\r
+ IN uint8_t rnr_nak_timeout,\r
+ IN OUT ib_qp_mod_t* const p_init OPTIONAL )\r
{\r
ib_api_status_t status;\r
kcep_t *p_cep;\r
\r
CL_ASSERT( h_al );\r
CL_ASSERT( p_cm_req );\r
- CL_ASSERT( p_init );\r
-\r
- /* TODO: Code P2P support. */\r
- if( p_cm_req->pfn_cm_req_cb )\r
- {\r
- AL_EXIT( AL_DBG_CM );\r
- return IB_UNSUPPORTED;\r
- }\r
\r
KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
p_cep = __lookup_cep( h_al, cid );\r
p_cep->p_mad = NULL;\r
/* Fall through. */\r
case CEP_STATE_IDLE:\r
- status = __save_user_req( p_cep, p_cm_req, &p_port_cep );\r
+ status = __save_user_req( p_cep, p_cm_req, rnr_nak_timeout, &p_port_cep );\r
if( status != IB_SUCCESS )\r
break;\r
\r
if( status != IB_SUCCESS )\r
break;\r
\r
- status = __format_req( p_cep, p_cm_req );\r
+ status = __format_req( p_port_cep, p_cep, p_cm_req );\r
if( status != IB_SUCCESS )\r
{\r
AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("Invalid pdata length.\n") );\r
}\r
\r
/* Format the INIT qp modify attributes. */\r
- p_init->req_state = IB_QPS_INIT;\r
- p_init->state.init.primary_port =\r
- p_cep->av[p_cep->idx_primary].attr.port_num;\r
- p_init->state.init.qkey = 0;\r
- p_init->state.init.pkey_index =\r
- p_cep->av[p_cep->idx_primary].pkey_index;\r
- p_init->state.init.access_ctrl = IB_AC_LOCAL_WRITE;\r
-\r
+ if( p_init )\r
+ {\r
+ p_init->req_state = IB_QPS_INIT;\r
+ p_init->state.init.primary_port =\r
+ p_cep->av[p_cep->idx_primary].attr.port_num;\r
+ p_init->state.init.qkey = 0;\r
+ p_init->state.init.pkey_index =\r
+ p_cep->av[p_cep->idx_primary].pkey_index;\r
+ p_init->state.init.access_ctrl = IB_AC_LOCAL_WRITE;\r
+ }\r
p_cep->state = CEP_STATE_PRE_REQ;\r
break;\r
\r
return status;\r
}\r
\r
+ib_api_status_t\r
+al_cep_pre_req(\r
+ IN ib_al_handle_t h_al,\r
+ IN net32_t cid,\r
+ IN const ib_cm_req_t* const p_cm_req,\r
+ OUT ib_qp_mod_t* const p_init )\r
+{\r
+ iba_cm_req req;\r
+ \r
+ RtlZeroMemory(&req, sizeof req);\r
+ req.service_id = p_cm_req->svc_id;\r
+\r
+ req.p_primary_path = p_cm_req->p_primary_path;\r
+ req.p_alt_path = p_cm_req->p_alt_path;\r
+\r
+ req.qpn = p_cm_req->h_qp->num;\r
+ req.qp_type = p_cm_req->qp_type;\r
+ req.starting_psn = req.qpn;\r
+\r
+ req.p_pdata = (void *) p_cm_req->p_req_pdata;\r
+ req.pdata_len = p_cm_req->req_length;\r
+\r
+ req.max_cm_retries = p_cm_req->max_cm_retries;\r
+ req.resp_res = p_cm_req->resp_res;\r
+ req.init_depth = p_cm_req->init_depth;\r
+ req.remote_resp_timeout = p_cm_req->remote_resp_timeout;\r
+ req.flow_ctrl = (uint8_t) p_cm_req->flow_ctrl;\r
+ req.local_resp_timeout = p_cm_req->local_resp_timeout;\r
+ req.rnr_retry_cnt = p_cm_req->rnr_retry_cnt;\r
+ req.retry_cnt = p_cm_req->retry_cnt;\r
+ req.srq = (uint8_t) (p_cm_req->h_qp->h_srq != NULL);\r
+\r
+ return kal_cep_pre_req(h_al, cid, &req, p_cm_req->rnr_nak_timeout, p_init);\r
+}\r
\r
ib_api_status_t\r
al_cep_send_req(\r
\r
static void\r
__save_user_rep(\r
+ IN cep_agent_t* const p_port_cep,\r
IN kcep_t* const p_cep,\r
- IN const ib_cm_rep_t* const p_cm_rep )\r
+ IN const iba_cm_rep* const p_cm_rep,\r
+ IN uint8_t rnr_nak_timeout )\r
{\r
AL_ENTER( AL_DBG_CM );\r
\r
- /* Cache the local QPN. */\r
- p_cep->local_qpn = p_cm_rep->h_qp->num;\r
- p_cep->rq_psn = p_cep->local_qpn;\r
+ p_cep->local_qpn = p_cm_rep->qpn;\r
+ p_cep->rq_psn = p_cm_rep->starting_psn;\r
p_cep->init_depth = p_cm_rep->init_depth;\r
\r
- ci_ca_lock_attr( p_cm_rep->h_qp->obj.p_ci_ca );\r
+ ci_ca_lock_attr( p_port_cep->h_ca->obj.p_ci_ca );\r
/* Check the CA's responder resource max and trim if necessary. */\r
- if( (p_cm_rep->h_qp->obj.p_ci_ca->p_pnp_attr->max_qp_resp_res <\r
- p_cep->resp_res) )\r
+ if( p_port_cep->h_ca->obj.p_ci_ca->p_pnp_attr->max_qp_resp_res <\r
+ p_cep->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_cep->resp_res = \r
- p_cm_rep->h_qp->obj.p_ci_ca->p_pnp_attr->max_qp_resp_res;\r
+ p_port_cep->h_ca->obj.p_ci_ca->p_pnp_attr->max_qp_resp_res;\r
}\r
- ci_ca_unlock_attr( p_cm_rep->h_qp->obj.p_ci_ca );\r
+ ci_ca_unlock_attr( p_port_cep->h_ca->obj.p_ci_ca );\r
\r
- p_cep->rnr_nak_timeout = p_cm_rep->rnr_nak_timeout;\r
+ p_cep->rnr_nak_timeout = rnr_nak_timeout;\r
\r
AL_EXIT( AL_DBG_CM );\r
}\r
\r
static ib_api_status_t\r
__format_rep(\r
+ IN cep_agent_t* const p_port_cep,\r
IN kcep_t* const p_cep,\r
- IN const ib_cm_rep_t* const p_cm_rep )\r
+ IN const iba_cm_rep* const p_cm_rep )\r
{\r
ib_api_status_t status;\r
mad_cm_rep_t *p_rep;\r
\r
p_rep->resp_resources = p_cep->resp_res;\r
\r
- ci_ca_lock_attr( p_cm_rep->h_qp->obj.p_ci_ca );\r
+ ci_ca_lock_attr( p_port_cep->h_ca->obj.p_ci_ca );\r
conn_rep_set_target_ack_delay(\r
- p_cm_rep->h_qp->obj.p_ci_ca->p_pnp_attr->local_ack_delay, p_rep );\r
- ci_ca_unlock_attr( p_cm_rep->h_qp->obj.p_ci_ca );\r
+ p_port_cep->h_ca->obj.p_ci_ca->p_pnp_attr->local_ack_delay, p_rep );\r
+ ci_ca_unlock_attr( p_port_cep->h_ca->obj.p_ci_ca );\r
\r
p_rep->initiator_depth = p_cep->init_depth;\r
\r
p_rep->local_ca_guid = p_cep->local_ca_guid;\r
\r
status = conn_rep_set_pdata(\r
- p_cm_rep->p_rep_pdata, p_cm_rep->rep_length, p_rep );\r
+ p_cm_rep->p_pdata, p_cm_rep->pdata_len, p_rep );\r
\r
conn_rep_clr_rsvd_fields( p_rep );\r
\r
\r
\r
\r
-ib_api_status_t\r
+static ib_api_status_t\r
__al_cep_pre_rep(\r
IN kcep_t *p_cep,\r
- IN void* context,\r
- IN const ib_cm_rep_t* const p_cm_rep,\r
- OUT ib_qp_mod_t* const p_init )\r
+ IN const iba_cm_rep* const p_cm_rep,\r
+ IN uint8_t rnr_nak_timeout,\r
+ OUT ib_qp_mod_t* const p_init OPTIONAL )\r
{\r
ib_api_status_t status;\r
cep_agent_t *p_port_cep;\r
AL_ENTER( AL_DBG_CM );\r
\r
CL_ASSERT( p_cm_rep );\r
- CL_ASSERT( p_init );\r
\r
switch( p_cep->state )\r
{\r
if( status != IB_SUCCESS )\r
break;\r
\r
- __save_user_rep( p_cep, p_cm_rep );\r
+ __save_user_rep( p_port_cep, p_cep, p_cm_rep, rnr_nak_timeout );\r
\r
- status = __format_rep( p_cep, p_cm_rep );\r
+ status = __format_rep( p_port_cep, p_cep, p_cm_rep );\r
if( status != IB_SUCCESS )\r
{\r
ib_put_mad( p_cep->p_mad );\r
}\r
\r
/* Format the INIT qp modify attributes. */\r
- p_init->req_state = IB_QPS_INIT;\r
- p_init->state.init.primary_port =\r
- p_cep->av[p_cep->idx_primary].attr.port_num;\r
- p_init->state.init.qkey = 0;\r
- p_init->state.init.pkey_index =\r
- p_cep->av[p_cep->idx_primary].pkey_index;\r
- p_init->state.init.access_ctrl = IB_AC_LOCAL_WRITE;\r
-\r
- p_cep->context = context;\r
-\r
+ if( p_init )\r
+ {\r
+ p_init->req_state = IB_QPS_INIT;\r
+ p_init->state.init.primary_port =\r
+ p_cep->av[p_cep->idx_primary].attr.port_num;\r
+ p_init->state.init.qkey = 0;\r
+ p_init->state.init.pkey_index =\r
+ p_cep->av[p_cep->idx_primary].pkey_index;\r
+ p_init->state.init.access_ctrl = IB_AC_LOCAL_WRITE;\r
+ }\r
/* Just OR in the PREP bit into the state. */\r
p_cep->state |= CEP_STATE_PREP;\r
break;\r
IN OUT net32_t* const p_cid,\r
OUT ib_qp_mod_t* const p_init )\r
{\r
- ib_api_status_t status;\r
kcep_t *p_cep;\r
+ iba_cm_rep rep;\r
KLOCK_QUEUE_HANDLE hdl;\r
+ ib_api_status_t status;\r
\r
- AL_ENTER( AL_DBG_CM );\r
+ RtlZeroMemory(&rep, sizeof rep);\r
+ rep.qpn = p_cm_rep->h_qp->num;\r
+ rep.starting_psn = rep.qpn;\r
\r
- CL_ASSERT( h_al );\r
- CL_ASSERT( p_cm_rep );\r
- CL_ASSERT( p_init );\r
+ rep.p_pdata = (void *) p_cm_rep->p_rep_pdata;\r
+ rep.pdata_len = p_cm_rep->rep_length;\r
\r
- KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
- if( *p_cid != AL_INVALID_CID )\r
- {\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
- AL_EXIT( AL_DBG_CM );\r
- return IB_RESOURCE_BUSY;\r
- }\r
+ rep.failover_accepted = p_cm_rep->failover_accepted;\r
+ rep.init_depth = p_cm_rep->init_depth;\r
+ rep.flow_ctrl = (uint8_t) p_cm_rep->flow_ctrl;\r
+ rep.rnr_retry_cnt = p_cm_rep->rnr_retry_cnt;\r
+ rep.srq = (uint8_t) (p_cm_rep->h_qp->h_srq != NULL);\r
\r
+ KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
p_cep = __lookup_cep( h_al, cid );\r
- if( !p_cep )\r
+ if (!p_cep )\r
{\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
- AL_EXIT( AL_DBG_CM );\r
- return IB_INVALID_HANDLE;\r
+ status = IB_INVALID_HANDLE;\r
+ goto out;\r
}\r
\r
- status = __al_cep_pre_rep( p_cep, context, p_cm_rep, p_init );\r
-\r
- if( status == IB_SUCCESS )\r
+ rep.resp_res = p_cep->resp_res;\r
+ status = __al_cep_pre_rep( p_cep, &rep, p_cm_rep->rnr_nak_timeout, p_init );\r
+ if ( status == IB_SUCCESS )\r
{\r
+ p_cep->context = context;\r
p_cep->pfn_destroy_cb = pfn_destroy_cb;\r
*p_cid = cid;\r
}\r
\r
+out:\r
KeReleaseInStackQueuedSpinLock( &hdl );\r
- AL_EXIT( AL_DBG_CM );\r
return status;\r
}\r
\r
\r
ib_api_status_t\r
-al_cep_pre_rep_ex(\r
+kal_cep_config_pre_rep_copy_cid(\r
IN ib_al_handle_t h_al,\r
IN net32_t cid,\r
IN al_pfn_cep_cb_t pfn_cb,\r
IN void* context,\r
IN ib_pfn_destroy_cb_t pfn_destroy_cb,\r
- IN const ib_cm_rep_t* const p_cm_rep,\r
+ IN const iba_cm_rep* const p_cm_rep,\r
+ IN uint8_t rnr_nak_timeout,\r
IN OUT net32_t* const p_cid,\r
OUT ib_qp_mod_t* const p_init )\r
{\r
- ib_api_status_t status;\r
kcep_t *p_cep;\r
KLOCK_QUEUE_HANDLE hdl;\r
-\r
- AL_ENTER( AL_DBG_CM );\r
+ ib_api_status_t status;\r
\r
CL_ASSERT( h_al );\r
CL_ASSERT( p_cm_rep );\r
CL_ASSERT( p_init );\r
\r
KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
- if( *p_cid != AL_INVALID_CID )\r
+ if (*p_cid != AL_INVALID_CID)\r
{\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
- AL_EXIT( AL_DBG_CM );\r
- return IB_RESOURCE_BUSY;\r
+ status = IB_RESOURCE_BUSY;\r
+ goto out;\r
}\r
\r
p_cep = __lookup_cep( h_al, cid );\r
- if( !p_cep )\r
+ if (!p_cep )\r
{\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
- AL_EXIT( AL_DBG_CM );\r
- return IB_INVALID_HANDLE;\r
+ status = IB_INVALID_HANDLE;\r
+ goto out;\r
}\r
\r
- status = __al_cep_pre_rep( p_cep, context, p_cm_rep, p_init );\r
-\r
- if( status == IB_SUCCESS )\r
+ status = __al_cep_pre_rep( p_cep, p_cm_rep, rnr_nak_timeout, p_init );\r
+ if ( status == IB_SUCCESS )\r
{\r
p_cep->pfn_cb = pfn_cb;\r
+ p_cep->context = context;\r
p_cep->pfn_destroy_cb = pfn_destroy_cb;\r
*p_cid = cid;\r
}\r
\r
+out:\r
+ KeReleaseInStackQueuedSpinLock( &hdl );\r
+ return status;\r
+}\r
+\r
+\r
+ib_api_status_t\r
+kal_cep_pre_rep(\r
+ IN ib_al_handle_t h_al,\r
+ IN net32_t cid,\r
+ IN const iba_cm_rep* const p_cm_rep,\r
+ IN uint8_t rnr_nak_timeout,\r
+ OUT ib_qp_mod_t* const p_init OPTIONAL )\r
+{\r
+ ib_api_status_t status;\r
+ kcep_t *p_cep;\r
+ KLOCK_QUEUE_HANDLE hdl;\r
+\r
+ AL_ENTER( AL_DBG_CM );\r
+\r
+ CL_ASSERT( h_al );\r
+ CL_ASSERT( p_cm_rep );\r
+\r
+ KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
+ p_cep = __lookup_cep( h_al, cid );\r
+ if( !p_cep )\r
+ {\r
+ status = IB_INVALID_HANDLE;\r
+ goto out;\r
+ }\r
+\r
+ status = __al_cep_pre_rep( p_cep, p_cm_rep, rnr_nak_timeout, p_init );\r
+\r
+out:\r
KeReleaseInStackQueuedSpinLock( &hdl );\r
AL_EXIT( AL_DBG_CM );\r
return status;\r
p_cep = __lookup_cep( h_al, cid );\r
if( !p_cep )\r
{\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
- AL_EXIT( AL_DBG_CM );\r
- return IB_INVALID_HANDLE;\r
+ status = IB_INVALID_HANDLE;\r
+ goto out;\r
}\r
\r
switch( p_cep->state )\r
p_port_cep = __get_cep_agent( p_cep );\r
if( !p_port_cep )\r
{\r
+ // Why call ib_put_mad() here but not below?\r
ib_put_mad( p_cep->p_mad );\r
+ // Why call __remove_cep() below but not here?\r
p_cep->state = CEP_STATE_IDLE;\r
status = IB_INSUFFICIENT_RESOURCES;\r
}\r
("Invalid state: %d\n", p_cep->state) );\r
status = IB_INVALID_STATE;\r
}\r
+out:\r
KeReleaseInStackQueuedSpinLock( &hdl );\r
AL_EXIT( AL_DBG_CM );\r
return status;\r
return status;\r
}\r
\r
+static void\r
+__format_path(ib_path_rec_t *p_path, req_path_info_t *p_info,\r
+ ib_net16_t pkey, uint8_t mtu)\r
+{\r
+ p_path->resv0 = 0;\r
+ p_path->dgid = p_info->local_gid;\r
+ p_path->sgid = p_info->remote_gid;\r
+ p_path->dlid = p_info->local_lid;\r
+ p_path->slid = p_info->remote_lid;\r
+ ib_path_rec_set_hop_flow_raw(p_path, p_info->hop_limit, \r
+ conn_req_path_get_flow_lbl(p_info), 0);\r
+ p_path->tclass = p_info->traffic_class;\r
+ p_path->num_path = 0;\r
+ p_path->pkey = pkey;\r
+ p_path->sl = conn_req_path_get_svc_lvl(p_info);\r
+ p_path->mtu = mtu;\r
+ p_path->rate = conn_req_path_get_pkt_rate(p_info);\r
+ p_path->pkt_life = conn_req_path_get_lcl_ack_timeout(p_info);\r
+ p_path->preference = 0;\r
+ p_path->resv1 = 0;\r
+ p_path->resv2 = 0;\r
+}\r
+\r
+static void\r
+__format_event_req(kcep_t *p_cep, mad_cm_req_t *p_mad, iba_cm_req_event *p_req)\r
+{\r
+ p_req->local_ca_guid = p_cep->local_ca_guid;\r
+ p_req->remote_ca_guid = p_cep->remote_ca_guid;\r
+ p_req->pkey_index = p_cep->av[0].pkey_index;\r
+ p_req->port_num = p_cep->av[0].attr.port_num;\r
+ p_req->req.service_id = p_mad->sid;\r
+\r
+ p_req->req.qpn = conn_req_get_lcl_qpn(p_mad);\r
+ p_req->req.qp_type = conn_req_get_qp_type(p_mad);\r
+ p_req->req.starting_psn = conn_req_get_starting_psn(p_mad);\r
+\r
+ p_req->req.p_pdata = p_mad->pdata;\r
+ p_req->req.pdata_len = IB_REQ_PDATA_SIZE;\r
+\r
+ p_req->req.max_cm_retries = conn_req_get_max_cm_retries(p_mad);\r
+ p_req->req.resp_res = conn_req_get_init_depth(p_mad);\r
+ p_req->req.init_depth = conn_req_get_resp_res(p_mad);\r
+ p_req->req.remote_resp_timeout = conn_req_get_resp_timeout(p_mad);\r
+ p_req->req.flow_ctrl = (uint8_t) conn_req_get_flow_ctrl(p_mad);\r
+ p_req->req.local_resp_timeout = conn_req_get_lcl_resp_timeout(p_mad);\r
+ p_req->req.rnr_retry_cnt = conn_req_get_rnr_retry_cnt(p_mad);\r
+ p_req->req.retry_cnt = conn_req_get_retry_cnt(p_mad);\r
+ p_req->req.srq = 0; // TODO: fix mad_cm_req_t\r
+\r
+ // We can re-use the MAD buffer if we're careful to read out the data\r
+ // that we need before it's overwritten.\r
+ p_req->req.p_primary_path = (ib_path_rec_t *) p_mad;\r
+ __format_path(p_req->req.p_primary_path, &p_mad->primary_path,\r
+ p_mad->pkey, conn_req_get_mtu(p_mad));\r
+\r
+ if (p_mad->alternate_path.remote_lid != 0) {\r
+ p_req->req.p_alt_path = p_req->req.p_primary_path + 1;\r
+ __format_path(p_req->req.p_alt_path, &p_mad->alternate_path,\r
+ p_req->req.p_primary_path->pkey,\r
+ p_req->req.p_primary_path->mtu);\r
+ } else {\r
+ p_req->req.p_alt_path = NULL;\r
+ }\r
+}\r
+\r
+static void\r
+__format_event_rep(mad_cm_rep_t *p_mad, iba_cm_rep_event *p_rep)\r
+{\r
+ p_rep->ca_guid = p_mad->local_ca_guid;\r
+ p_rep->target_ack_delay = conn_rep_get_target_ack_delay(p_mad);\r
+ p_rep->rep.qpn = conn_rep_get_lcl_qpn(p_mad);\r
+ p_rep->rep.starting_psn = conn_rep_get_starting_psn(p_mad);\r
+\r
+ p_rep->rep.p_pdata = p_mad->pdata;\r
+ p_rep->rep.pdata_len = IB_REP_PDATA_SIZE;\r
+\r
+ p_rep->rep.failover_accepted = conn_rep_get_failover(p_mad);\r
+ p_rep->rep.resp_res = p_mad->initiator_depth;\r
+ p_rep->rep.init_depth = p_mad->resp_resources;\r
+ p_rep->rep.flow_ctrl = (uint8_t) conn_rep_get_e2e_flow_ctl(p_mad);\r
+ p_rep->rep.rnr_retry_cnt = conn_rep_get_rnr_retry_cnt(p_mad);\r
+}\r
+\r
+static void\r
+__format_event_rej(mad_cm_rej_t *p_mad, iba_cm_rej_event *p_rej)\r
+{\r
+ p_rej->ari = p_mad->ari;\r
+ p_rej->p_pdata = p_mad->pdata;\r
+ p_rej->reason = p_mad->reason;\r
+ p_rej->ari_length = conn_rej_get_ari_len(p_mad);\r
+ p_rej->pdata_len = IB_MRA_PDATA_SIZE;\r
+}\r
+\r
+static void\r
+__format_event_mra(mad_cm_mra_t *p_mad, iba_cm_mra_event *p_mra)\r
+{\r
+ p_mra->p_pdata = p_mad->pdata;\r
+ p_mra->pdata_len = IB_MRA_PDATA_SIZE;\r
+ p_mra->service_timeout = conn_mra_get_svc_timeout(p_mad);\r
+}\r
+\r
+static void\r
+__format_event_pdata(kcep_t *p_cep, iba_cm_pdata *p_pdata)\r
+{\r
+ p_pdata->p_pdata = p_cep->pdata;\r
+ p_pdata->pdata_len = p_cep->psize;\r
+}\r
+\r
+/*\r
+ * Called after polling a MAD from a CEP to parse the received CM message\r
+ * into readable event data.\r
+ */\r
+void\r
+kal_cep_format_event(\r
+ IN ib_al_handle_t h_al,\r
+ IN net32_t cid,\r
+ IN ib_mad_element_t *p_mad,\r
+ IN OUT iba_cm_event *p_event)\r
+{\r
+ KLOCK_QUEUE_HANDLE hdl;\r
+ kcep_t *p_cep;\r
+ \r
+ KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
+ p_cep = __lookup_cep( h_al, cid );\r
+ KeReleaseInStackQueuedSpinLock( &hdl );\r
+\r
+ switch (p_mad->p_mad_buf->attr_id) {\r
+ case CM_REQ_ATTR_ID:\r
+ if (p_mad->status == IB_SUCCESS) {\r
+ p_event->type = iba_cm_req_received;\r
+ __format_event_req(p_cep, (mad_cm_req_t*) p_mad->p_mad_buf, &p_event->data.req);\r
+ } else {\r
+ p_event->type = iba_cm_req_error;\r
+ }\r
+ break;\r
+ case CM_REP_ATTR_ID:\r
+ if (p_mad->status == IB_SUCCESS) {\r
+ p_event->type = iba_cm_rep_received;\r
+ __format_event_rep((mad_cm_rep_t*) p_mad->p_mad_buf, &p_event->data.rep);\r
+ } else {\r
+ p_event->type = iba_cm_rep_error;\r
+ }\r
+ break;\r
+ case CM_RTU_ATTR_ID:\r
+ p_event->type = iba_cm_rtu_received;\r
+ __format_event_pdata(p_cep, &p_event->data.rtu);\r
+ break;\r
+ case CM_DREQ_ATTR_ID:\r
+ if (p_mad->status == IB_SUCCESS) {\r
+ p_event->type = iba_cm_dreq_received;\r
+ __format_event_pdata(p_cep, &p_event->data.dreq);\r
+ } else {\r
+ p_event->type = iba_cm_dreq_error;\r
+ }\r
+ break;\r
+ case CM_DREP_ATTR_ID:\r
+ p_event->type = iba_cm_drep_received;\r
+ __format_event_pdata(p_cep, &p_event->data.drep);\r
+ break;\r
+ case CM_REJ_ATTR_ID:\r
+ p_event->type = iba_cm_rej_received;\r
+ __format_event_rej((mad_cm_rej_t*) p_mad->p_mad_buf, &p_event->data.rej);\r
+ break;\r
+ case CM_MRA_ATTR_ID:\r
+ p_event->type = iba_cm_mra_received;\r
+ __format_event_mra((mad_cm_mra_t*) p_mad->p_mad_buf, &p_event->data.mra);\r
+ break;\r
+ case CM_LAP_ATTR_ID:\r
+ if (p_mad->status == IB_SUCCESS) {\r
+ p_event->type = iba_cm_lap_received;\r
+ // TODO: format lap event\r
+ } else {\r
+ p_event->type = iba_cm_lap_error;\r
+ }\r
+ break;\r
+ case CM_APR_ATTR_ID:\r
+ p_event->type = iba_cm_apr_received;;\r
+ // TODO: format apr event\r
+ break;\r
+ case CM_SIDR_REQ_ATTR_ID:\r
+ if (p_mad->status == IB_SUCCESS) {\r
+ p_event->type = iba_cm_sidr_req_received;\r
+ // TODO: format sidr req event\r
+ } else {\r
+ p_event->type = iba_cm_sidr_req_error;\r
+ }\r
+ break;\r
+ case CM_SIDR_REP_ATTR_ID:\r
+ p_event->type = iba_cm_sidr_rep_received;\r
+ // TODO: format sidr rep event\r
+ break;\r
+ default:\r
+ CL_ASSERT(0);\r
+ }\r
+}\r
+\r
+\r
+ib_api_status_t\r
+al_cep_get_init_attr(\r
+ IN ib_al_handle_t h_al,\r
+ IN net32_t cid,\r
+ OUT ib_qp_mod_t* const p_init )\r
+{\r
+ ib_api_status_t status;\r
+ kcep_t *p_cep;\r
+ KLOCK_QUEUE_HANDLE hdl;\r
+\r
+ AL_ENTER( AL_DBG_CM );\r
+\r
+ KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
+ p_cep = __lookup_cep( h_al, cid );\r
+ if( !p_cep )\r
+ {\r
+ status = IB_INVALID_HANDLE;\r
+ goto out;\r
+ }\r
+\r
+ switch( p_cep->state )\r
+ {\r
+ case CEP_STATE_PRE_REQ:\r
+ case CEP_STATE_REQ_RCVD:\r
+ case CEP_STATE_PRE_REP:\r
+ case CEP_STATE_REQ_SENT:\r
+ case CEP_STATE_REQ_MRA_RCVD:\r
+ case CEP_STATE_REQ_MRA_SENT:\r
+ case CEP_STATE_PRE_REP_MRA_SENT:\r
+ case CEP_STATE_REP_RCVD:\r
+ case CEP_STATE_REP_SENT:\r
+ case CEP_STATE_REP_MRA_RCVD:\r
+ case CEP_STATE_REP_MRA_SENT:\r
+ case CEP_STATE_ESTABLISHED:\r
+ /* Format the INIT qp modify attributes. */\r
+ cl_memclr(p_init, sizeof(ib_qp_mod_t));\r
+ p_init->req_state = IB_QPS_INIT;\r
+ p_init->state.init.primary_port =\r
+ p_cep->av[p_cep->idx_primary].attr.port_num;\r
+ p_init->state.init.pkey_index =\r
+ p_cep->av[p_cep->idx_primary].pkey_index;\r
+ p_init->state.init.access_ctrl = IB_AC_LOCAL_WRITE;\r
+ if ( p_cep->resp_res )\r
+ {\r
+ p_init->state.init.access_ctrl |= IB_AC_RDMA_READ |\r
+ IB_AC_RDMA_WRITE |\r
+ IB_AC_ATOMIC;\r
+ }\r
+ status = IB_SUCCESS;\r
+ break;\r
+ default:\r
+ status = IB_INVALID_STATE;\r
+ break;\r
+ }\r
+\r
+out:\r
+ KeReleaseInStackQueuedSpinLock( &hdl );\r
+ AL_EXIT( AL_DBG_CM );\r
+ return status;\r
+}\r
\r
ib_api_status_t\r
al_cep_get_rtr_attr(\r
\r
switch( p_cep->state )\r
{\r
+ case CEP_STATE_REQ_RCVD:\r
+ case CEP_STATE_REQ_MRA_SENT:\r
case CEP_STATE_PRE_REP:\r
case CEP_STATE_PRE_REP_MRA_SENT:\r
case CEP_STATE_REP_SENT:\r
NTSTATUS nt_status;\r
ib_cm_req_t cm_req;\r
ib_qp_mod_t qp_mod;\r
+ al_conn_qp_t *p_qp;\r
\r
AL_ENTER( AL_DBG_NDI );\r
\r
}\r
\r
/* Get a CEP and bind it to the QP. */\r
- status = al_create_cep(\r
- qp_get_al( h_qp ), __ndi_cm_handler, h_qp, deref_al_obj,\r
- &((al_conn_qp_t*)h_qp)->cid );\r
+ p_qp = (al_conn_qp_t*)h_qp;\r
+ cl_spinlock_acquire( &h_qp->obj.lock );\r
+ if( h_qp->obj.state != CL_DESTROYING && p_qp->cid == AL_INVALID_CID )\r
+ {\r
+ status = al_create_cep( qp_get_al( h_qp ), __ndi_cm_handler,\r
+ &h_qp->obj, deref_al_obj, &p_qp->cid );\r
+ }\r
+ else \r
+ {\r
+ status = IB_RESOURCE_BUSY;\r
+ }\r
+ cl_spinlock_release( &h_qp->obj.lock );\r
if( status != IB_SUCCESS )\r
{\r
h_qp->p_irp_queue->state = NDI_CM_IDLE;\r
AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
("al_create_cep returned %s.\n", ib_get_err_str( status )) );\r
- return STATUS_INSUFFICIENT_RESOURCES;\r
+ return ib_to_ntstatus( status );\r
}\r
AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
("Created Active CEP with cid %d, h_al %p, context %p\n",\r
- ((al_conn_qp_t*)h_qp)->cid, qp_get_al( h_qp ), h_qp ) );\r
+ p_qp->cid, qp_get_al( h_qp ), h_qp ) );\r
\r
ref_al_obj( &h_qp->obj ); /* Take CEP reference. */\r
\r
__ndi_fill_cm_req( h_qp, p_req, p_path_rec, &cm_req );\r
\r
/* prepare CEP for connection */\r
- status = al_cep_pre_req( qp_get_al( h_qp ),\r
- ((al_conn_qp_t*)h_qp)->cid, &cm_req, &qp_mod );\r
+ status = al_cep_pre_req( qp_get_al( h_qp ), p_qp->cid, &cm_req, &qp_mod );\r
if( status != STATUS_SUCCESS )\r
{\r
AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
}\r
\r
/* send CM REQ */\r
- status = al_cep_send_req( qp_get_al( h_qp ), ((al_conn_qp_t*)h_qp)->cid );\r
+ status = al_cep_send_req( qp_get_al( h_qp ), p_qp->cid );\r
if( status != IB_SUCCESS )\r
{\r
AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
return STATUS_SUCCESS;\r
\r
error:\r
- al_destroy_cep( qp_get_al( h_qp ), &((al_conn_qp_t*)h_qp)->cid, TRUE );\r
+ al_destroy_cep( qp_get_al( h_qp ), &p_qp->cid, TRUE );\r
\r
switch( status )\r
{\r
__ndi_fill_cm_rep(\r
IN ib_qp_handle_t const h_qp,\r
IN ual_ndi_rep_cm_ioctl_in_t *p_rep,\r
- OUT ib_cm_rep_t *p_cm_rep)\r
+ OUT iba_cm_rep *p_cm_rep)\r
{\r
AL_ENTER( AL_DBG_NDI );\r
\r
- memset( p_cm_rep, 0, sizeof(ib_cm_rep_t) );\r
+ memset( p_cm_rep, 0, sizeof(*p_cm_rep) );\r
\r
- p_cm_rep->p_rep_pdata = p_rep->pdata;\r
- p_cm_rep->rep_length = sizeof(p_rep->pdata);\r
+ p_cm_rep->p_pdata = p_rep->pdata;\r
+ p_cm_rep->pdata_len = sizeof(p_rep->pdata);\r
\r
- p_cm_rep->qp_type = IB_QPT_RELIABLE_CONN;\r
- p_cm_rep->h_qp = h_qp;\r
+ p_cm_rep->qpn = h_qp->num;\r
\r
- p_cm_rep->access_ctrl = IB_AC_RDMA_READ | IB_AC_RDMA_WRITE | IB_AC_LOCAL_WRITE;\r
p_cm_rep->init_depth = p_rep->init_depth;\r
- p_cm_rep->target_ack_delay = 10;\r
p_cm_rep->failover_accepted = IB_FAILOVER_ACCEPT_UNSUPPORTED;\r
p_cm_rep->flow_ctrl = TRUE; /* HCAs must support end-to-end flow control. */\r
- p_cm_rep->rnr_nak_timeout = QP_ATTRIB_RNR_NAK_TIMEOUT;\r
p_cm_rep->rnr_retry_cnt = QP_ATTRIB_RNR_RETRY;\r
\r
AL_EXIT( AL_DBG_NDI );\r
IN PIRP p_irp )\r
{\r
IO_STACK_LOCATION *p_io_stack;\r
- ib_cm_rep_t cm_rep;\r
+ iba_cm_rep cm_rep;\r
ib_qp_mod_t qp_mod;\r
ib_api_status_t status;\r
ual_ndi_rep_cm_ioctl_in_t *p_rep = \r
ref_al_obj( &h_qp->obj ); /* Take CEP reference. */\r
\r
/* prepare Passive CEP for connection */\r
- status = al_cep_pre_rep_ex(\r
- qp_get_al( h_qp ), p_rep->cid, __ndi_cm_handler, h_qp, deref_al_obj,\r
- &cm_rep, &((al_conn_qp_t*)h_qp)->cid, &qp_mod );\r
+ status = kal_cep_config_pre_rep_copy_cid(\r
+ qp_get_al( h_qp ), p_rep->cid, __ndi_cm_handler, &h_qp->obj, deref_al_obj,\r
+ &cm_rep, QP_ATTRIB_RNR_NAK_TIMEOUT, &((al_conn_qp_t*)h_qp)->cid, &qp_mod);\r
if( status != IB_SUCCESS )\r
{\r
IoFreeWorkItem( p_irp->Tail.Overlay.DriverContext[1] );\r
al_destroy_cep( qp_get_al( h_qp ), &p_rep->cid, FALSE );\r
deref_al_obj( &h_qp->obj ); /* Release CEP reference. */\r
AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
- ("al_cep_pre_rep_ex returned %s.\n", ib_get_err_str( status )) );\r
+ ("kal_cep_config_pre_rep_copy_cid returned %s.\n", ib_get_err_str( status )) );\r
switch (status)\r
{\r
case IB_INVALID_HANDLE:\r
#include "complib/cl_memory.h"\r
#include <initguid.h>\r
#include "iba/ib_ci_ifc.h"\r
+#include "iba/ib_cm_ifc.h"\r
+#include "al_cm_cep.h"\r
\r
\r
/* Interface names are generated by IoRegisterDeviceInterface. */\r
static UNICODE_STRING al_ifc_name;\r
static UNICODE_STRING ci_ifc_name;\r
+static UNICODE_STRING cm_ifc_name;\r
\r
KEVENT g_ControlEvent;\r
ULONG g_bfi_InstanceCount;\r
IN DEVICE_OBJECT* const p_dev_obj,\r
IN IO_STACK_LOCATION* const p_io_stack );\r
\r
+static NTSTATUS\r
+__query_cm_ifc(\r
+ IN DEVICE_OBJECT* const p_dev_obj,\r
+ IN IO_STACK_LOCATION* const p_io_stack );\r
+\r
static NTSTATUS\r
fdo_query_interface(\r
IN DEVICE_OBJECT* const p_dev_obj,\r
#pragma alloc_text (PAGE, fdo_query_bus_relations)\r
#pragma alloc_text (PAGE, __query_al_ifc)\r
#pragma alloc_text (PAGE, __query_ci_ifc)\r
+#pragma alloc_text (PAGE, __query_cm_ifc)\r
#pragma alloc_text (PAGE, __get_relations)\r
#pragma alloc_text (PAGE, fdo_query_interface)\r
#pragma alloc_text (PAGE_PNP, __fdo_query_power)\r
{\r
BUS_PRINT( BUS_DBG_ERROR, \r
("Failed to create ControlDeviceObject, status %x.\n",status) );\r
- goto bail;\r
+ goto err1;\r
}\r
IoDeleteSymbolicLink( &dos_name );\r
status = IoCreateSymbolicLink( &dos_name, &dev_name );\r
if( !NT_SUCCESS(status) )\r
{\r
- IoDeleteDevice( p_dev_obj );\r
BUS_PRINT( BUS_DBG_ERROR,\r
("Failed to create symlink for dos name.\n") );\r
- goto bail;\r
+ goto err2;\r
}\r
}\r
else {\r
{\r
BUS_PRINT( BUS_DBG_ERROR, \r
("Failed to create bus root FDO device.\n") );\r
- goto bail;\r
+ goto err1;\r
}\r
}\r
\r
p_next_do = IoAttachDeviceToDeviceStack( p_dev_obj, p_pdo );\r
if( !p_next_do )\r
{\r
- IoDeleteDevice( p_dev_obj );\r
BUS_PRINT( BUS_DBG_ERROR, ("IoAttachToDeviceStack failed.\n") );\r
status = STATUS_NO_SUCH_DEVICE;\r
- goto bail;\r
+ goto err2;\r
}\r
\r
cl_init_pnp_po_ext( p_dev_obj, p_next_do, p_pdo, bus_globals.dbg_lvl,\r
&al_ifc_name );\r
if( !NT_SUCCESS( status ) )\r
{\r
- IoDetachDevice( p_ext->cl_ext.p_next_do );\r
- IoDeleteDevice( p_dev_obj );\r
BUS_PRINT( BUS_DBG_ERROR, \r
("IoRegisterDeviceInterface for upper interface returned %08x\n",\r
status) );\r
status = STATUS_NO_SUCH_DEVICE;\r
- goto bail;\r
+ goto err3;\r
}\r
\r
/* Register the lower (CI) interface (the one used by HCA VPDs). */\r
&ci_ifc_name );\r
if( !NT_SUCCESS( status ) )\r
{\r
- IoDetachDevice( p_ext->cl_ext.p_next_do );\r
- IoDeleteDevice( p_dev_obj );\r
BUS_PRINT( BUS_DBG_ERROR, \r
("IoRegisterDeviceInterface for lower interface returned %08x\n",\r
status) );\r
status = STATUS_NO_SUCH_DEVICE;\r
- goto bail;\r
+ goto err3;\r
+ }\r
+\r
+ status = IoRegisterDeviceInterface( p_pdo, &GUID_INFINIBAND_INTERFACE_CM, NULL,\r
+ &cm_ifc_name );\r
+ if( !NT_SUCCESS( status ) )\r
+ {\r
+ BUS_PRINT( BUS_DBG_ERROR, \r
+ ("IoRegisterDeviceInterface for cm interface returned %08x\n",\r
+ status) );\r
+ status = STATUS_NO_SUCH_DEVICE;\r
+ goto err3;\r
}\r
\r
adxit:\r
BUS_EXIT( BUS_DBG_PNP );\r
return STATUS_SUCCESS;\r
\r
-bail:\r
+err3:\r
+ IoDetachDevice( p_ext->cl_ext.p_next_do );\r
+err2:\r
+ IoDeleteDevice( p_dev_obj );\r
+err1:\r
BUS_PRINT( BUS_DBG_PNP, ("%s exit status 0x%x\n", p_bfi->whoami,status) );\r
ic = free_bfi(p_bfi);\r
/* if last Bus filter, then cleanup */\r
\r
status = IoSetDeviceInterfaceState( &ci_ifc_name, TRUE );\r
ASSERT( NT_SUCCESS( status ) );\r
+\r
+ status = IoSetDeviceInterfaceState( &cm_ifc_name, TRUE );\r
+ ASSERT( NT_SUCCESS( status ) );\r
}\r
\r
BUS_PRINT(BUS_DBG_PNP,\r
ASSERT( NT_SUCCESS( status ) );\r
status = IoSetDeviceInterfaceState( &ci_ifc_name, FALSE );\r
ASSERT( NT_SUCCESS( status ) );\r
+ status = IoSetDeviceInterfaceState( &cm_ifc_name, FALSE );\r
+ ASSERT( NT_SUCCESS( status ) );\r
\r
/* Release the memory allocated for the interface symbolic names. */\r
+ RtlFreeUnicodeString( &cm_ifc_name );\r
RtlFreeUnicodeString( &ci_ifc_name );\r
RtlFreeUnicodeString( &al_ifc_name );\r
\r
}\r
\r
\r
+static NTSTATUS\r
+__query_cm_ifc(\r
+ IN DEVICE_OBJECT* const p_dev_obj,\r
+ IN IO_STACK_LOCATION* const p_io_stack )\r
+{\r
+ INFINIBAND_INTERFACE_CM *p_ifc;\r
+\r
+ BUS_ENTER( BUS_DBG_PNP );\r
+\r
+ if( p_io_stack->Parameters.QueryInterface.Version != IbaCmVersion(1, 0) )\r
+ {\r
+ BUS_TRACE_EXIT( BUS_DBG_PNP, ("Incorrect interface version (%d)\n",\r
+ p_io_stack->Parameters.QueryInterface.Version ) );\r
+ return STATUS_NOT_SUPPORTED;\r
+ }\r
+\r
+ if( p_io_stack->Parameters.QueryInterface.Size < sizeof(INFINIBAND_INTERFACE_CM) )\r
+ {\r
+ BUS_TRACE_EXIT( BUS_DBG_PNP, \r
+ ("Buffer too small (%d given, %d required).\n",\r
+ p_io_stack->Parameters.QueryInterface.Size, sizeof(INFINIBAND_INTERFACE_CM)) );\r
+ return STATUS_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ /* Copy the interface. */\r
+ p_ifc = (INFINIBAND_INTERFACE_CM*)p_io_stack->Parameters.QueryInterface.Interface;\r
+\r
+ p_ifc->InterfaceHeader.Size = sizeof(INFINIBAND_INTERFACE_CM);\r
+ p_ifc->InterfaceHeader.Version = IbaCmVersion(1, 0);\r
+ p_ifc->InterfaceHeader.Context = p_dev_obj;\r
+ p_ifc->InterfaceHeader.InterfaceReference = al_ref_ifc;\r
+ p_ifc->InterfaceHeader.InterfaceDereference = al_deref_ifc;\r
+ cm_get_interface(&p_ifc->CM);\r
+\r
+ /* take the reference before returning. */\r
+ al_ref_ifc( p_dev_obj );\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+\r
static NTSTATUS\r
fdo_query_interface(\r
IN DEVICE_OBJECT* const p_dev_obj,\r
{\r
status = __query_ci_ifc( p_dev_obj, p_io_stack );\r
}\r
+ else if( IsEqualGUID( p_io_stack->Parameters.QueryInterface.InterfaceType,\r
+ &GUID_INFINIBAND_INTERFACE_CM ) )\r
+ {\r
+ status = __query_cm_ifc( p_dev_obj, p_io_stack );\r
+ }\r
else\r
{\r
status = p_irp->IoStatus.Status;\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 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
+\r
+#ifndef _ib_cm_ifc_h_\r
+#define _ib_cm_ifc_h_\r
+\r
+#include <initguid.h>\r
+#include <iba/ib_al_ifc.h>\r
+#include <iba/ib_types.h>\r
+#include <iba/ib_al.h>\r
+\r
+struct _iba_cm_event;\r
+\r
+typedef struct _iba_cm_id\r
+{\r
+ void *context;\r
+ NTSTATUS (*callback)(struct _iba_cm_id *p_id, struct _iba_cm_event *p_event);\r
+ net32_t cid;\r
+\r
+} iba_cm_id;\r
+\r
+typedef struct _iba_cm_req\r
+{\r
+ ib_net64_t service_id;\r
+\r
+ ib_path_rec_t *p_primary_path;\r
+ ib_path_rec_t *p_alt_path;\r
+\r
+ net32_t qpn;\r
+ ib_qp_type_t qp_type;\r
+ net32_t starting_psn;\r
+\r
+ void *p_pdata;\r
+ uint8_t pdata_len;\r
+\r
+ uint8_t max_cm_retries;\r
+ uint8_t resp_res;\r
+ uint8_t init_depth;\r
+ uint8_t remote_resp_timeout;\r
+ uint8_t flow_ctrl;\r
+ uint8_t local_resp_timeout;\r
+ uint8_t rnr_retry_cnt;\r
+ uint8_t retry_cnt;\r
+ uint8_t srq;\r
+\r
+} iba_cm_req;\r
+\r
+typedef struct _iba_cm_req_event\r
+{\r
+ iba_cm_req req;\r
+ net64_t local_ca_guid;\r
+ net64_t remote_ca_guid;\r
+ uint16_t pkey_index;\r
+ uint8_t port_num;\r
+\r
+} iba_cm_req_event;\r
+\r
+typedef struct _iba_cm_rep\r
+{\r
+ net32_t qpn;\r
+ net32_t starting_psn;\r
+\r
+ void *p_pdata;\r
+ uint8_t pdata_len;\r
+\r
+ ib_cm_failover_t failover_accepted;\r
+ uint8_t resp_res;\r
+ uint8_t init_depth;\r
+ uint8_t flow_ctrl;\r
+ uint8_t rnr_retry_cnt;\r
+ uint8_t srq;\r
+\r
+} iba_cm_rep;\r
+\r
+typedef struct _iba_cm_rep_event\r
+{\r
+ iba_cm_rep rep;\r
+ net64_t ca_guid;\r
+ uint8_t target_ack_delay;\r
+\r
+} iba_cm_rep_event;\r
+\r
+typedef struct _iba_cm_pdata\r
+{\r
+ void *p_pdata;\r
+ uint8_t pdata_len;\r
+\r
+} iba_cm_pdata;\r
+typedef iba_cm_pdata iba_cm_rtu_event;\r
+typedef iba_cm_pdata iba_cm_dreq_event;\r
+typedef iba_cm_pdata iba_cm_drep_event;\r
+\r
+typedef struct _iba_cm_rej_event\r
+{\r
+ void *ari;\r
+ void *p_pdata;\r
+ ib_rej_status_t reason;\r
+ uint8_t ari_length;\r
+ uint8_t pdata_len;\r
+ \r
+} iba_cm_rej_event;\r
+\r
+typedef struct _iba_cm_mra_event\r
+{\r
+ void *p_pdata;\r
+ uint8_t pdata_len;\r
+ uint8_t service_timeout;\r
+\r
+} iba_cm_mra_event;\r
+\r
+typedef struct _iba_cm_lap\r
+{\r
+ ib_path_rec_t *p_alt_path;\r
+ void *p_pdata;\r
+ uint8_t pdata_len;\r
+ uint8_t remote_resp_timeout;\r
+\r
+} iba_cm_lap;\r
+typedef iba_cm_lap iba_cm_lap_event;\r
+\r
+typedef struct _iba_cm_apr\r
+{\r
+ void *p_pdata;\r
+ ib_apr_info_t *p_info;\r
+ uint8_t pdata_len;\r
+ uint8_t info_length;\r
+ ib_apr_status_t status;\r
+\r
+} iba_cm_apr;\r
+typedef iba_cm_apr iba_cm_apr_event;\r
+\r
+typedef struct _iba_cm_sidr_req\r
+{\r
+ ib_net64_t service_id;\r
+ ib_path_rec_t *p_path;\r
+ void *p_pdata;\r
+ uint8_t pdata_len;\r
+ uint8_t max_cm_retries;\r
+ uint32_t timeout;\r
+\r
+} iba_cm_sidr_req;\r
+\r
+typedef struct _iba_cm_sidr_req_event\r
+{\r
+ iba_cm_sidr_req sidr_req;\r
+ net64_t ca_guid;\r
+ uint16_t pkey_index;\r
+ uint8_t port_num;\r
+\r
+} iba_cm_sidr_req_event;\r
+\r
+typedef struct _iba_cm_sidr_rep\r
+{\r
+ net32_t qpn;\r
+ net32_t qkey;\r
+ void *p_pdata;\r
+ void *p_info;\r
+ uint8_t pdata_len;\r
+ uint8_t info_len;\r
+ ib_sidr_status_t status;\r
+\r
+} iba_cm_sidr_rep;\r
+typedef iba_cm_sidr_rep iba_cm_sidr_rep_event;\r
+\r
+typedef enum _iba_cm_event_type\r
+{\r
+ iba_cm_req_error,\r
+ iba_cm_req_received,\r
+ iba_cm_rep_error,\r
+ iba_cm_rep_received,\r
+ iba_cm_rtu_received,\r
+ iba_cm_dreq_error,\r
+ iba_cm_dreq_received,\r
+ iba_cm_drep_received,\r
+ iba_cm_rej_received,\r
+ iba_cm_mra_received,\r
+ iba_cm_lap_error,\r
+ iba_cm_lap_received,\r
+ iba_cm_apr_received,\r
+ iba_cm_sidr_req_error,\r
+ iba_cm_sidr_req_received,\r
+ iba_cm_sidr_rep_received\r
+\r
+} iba_cm_event_type;\r
+\r
+typedef struct _iba_cm_event\r
+{\r
+ iba_cm_event_type type;\r
+ union\r
+ {\r
+ iba_cm_req_event req;\r
+ iba_cm_rep_event rep;\r
+ iba_cm_rtu_event rtu;\r
+ iba_cm_dreq_event dreq;\r
+ iba_cm_drep_event drep;\r
+ iba_cm_rej_event rej;\r
+ iba_cm_mra_event mra;\r
+ iba_cm_lap_event lap;\r
+ iba_cm_apr_event apr;\r
+ iba_cm_sidr_req_event sidr_req;\r
+ iba_cm_sidr_rep_event sidr_rep;\r
+\r
+ } data;\r
+\r
+} iba_cm_event;\r
+\r
+typedef struct _iba_cm_interface\r
+{\r
+ NTSTATUS (*create_id)(NTSTATUS (*callback)(iba_cm_id *p_id,\r
+ iba_cm_event *p_event),\r
+ void *context, iba_cm_id **pp_id);\r
+ void (*destroy_id)(iba_cm_id *p_id);\r
+\r
+ NTSTATUS (*listen)(iba_cm_id *p_id, net64_t service_id, void *p_compare_buf,\r
+ uint8_t compare_len, uint8_t compare_offset);\r
+\r
+ NTSTATUS (*send_req)(iba_cm_id *p_id, iba_cm_req *p_req);\r
+ NTSTATUS (*send_rep)(iba_cm_id *p_id, iba_cm_rep *p_rep);\r
+ NTSTATUS (*send_rtu)(iba_cm_id *p_id, void *p_pdata, uint8_t pdata_len);\r
+\r
+ NTSTATUS (*send_dreq)(iba_cm_id *p_id, void *p_pdata, uint8_t pdata_len);\r
+ NTSTATUS (*send_drep)(iba_cm_id *p_id, void *p_pdata, uint8_t pdata_len);\r
+\r
+ NTSTATUS (*send_rej)(iba_cm_id *p_id, ib_rej_status_t status,\r
+ void *p_ari, uint8_t ari_len,\r
+ void *p_pdata, uint8_t pdata_len);\r
+ NTSTATUS (*send_mra)(iba_cm_id *p_id, uint8_t service_timeout,\r
+ void *p_pdata, uint8_t pdata_len);\r
+\r
+ NTSTATUS (*send_lap)(iba_cm_id *p_id, iba_cm_lap *p_lap);\r
+ NTSTATUS (*send_apr)(iba_cm_id *p_id, iba_cm_apr *p_apr);\r
+\r
+ NTSTATUS (*send_sidr_req)(iba_cm_id *p_id, iba_cm_sidr_req *p_req);\r
+ NTSTATUS (*send_sidr_rep)(iba_cm_id *p_id, iba_cm_sidr_rep *p_rep);\r
+\r
+ NTSTATUS (*get_qp_attr)(iba_cm_id *p_id, ib_qp_state_t state,\r
+ ib_qp_mod_t *p_attr);\r
+\r
+ NTSTATUS (*migrate)(iba_cm_id *p_id);\r
+ NTSTATUS (*established)(iba_cm_id *p_id);\r
+\r
+} iba_cm_interface;\r
+\r
+static inline USHORT IbaCmVersion(UINT8 Major, UINT8 Minor)\r
+{\r
+ return ((USHORT) Major << 8) | ((USHORT) Minor);\r
+}\r
+\r
+static inline UINT8 IbaCmVersionMajor(USHORT Version)\r
+{\r
+ return (UINT8) (Version >> 8);\r
+}\r
+\r
+static inline UINT8 IbaCmVersionMinor(USHORT Version)\r
+{\r
+ return (UINT8) Version;\r
+}\r
+\r
+// {EACC1466-BB2D-4478-B5BE-40EDF7EE08AB}\r
+DEFINE_GUID(GUID_INFINIBAND_INTERFACE_CM, 0xeacc1466, 0xbb2d, 0x4478,\r
+ 0xb5, 0xbe, 0x40, 0xed, 0xf7, 0xee, 0x8, 0xab);\r
+\r
+typedef struct _INFINIBAND_INTERFACE_CM\r
+{\r
+ INTERFACE InterfaceHeader;\r
+ iba_cm_interface CM;\r
+\r
+} INFINIBAND_INTERFACE_CM;\r
+\r
+#endif // _ib_cm_ifc_h_
\ No newline at end of file