\r
#include <windows.h>\r
#include <rdma\winverbs.h>\r
+#include <errno.h>\r
+#include <comp_channel.h>\r
\r
#ifdef __cplusplus\r
extern "C" {\r
typedef unsigned __int32 uint32_t;\r
typedef unsigned __int64 uint64_t;\r
\r
+#define EOVERFLOW WV_BUFFER_OVERFLOW\r
+#define EISCONN WV_CONNECTION_ACTIVE\r
+#define ECONNREFUSED WV_CONNECTION_REFUSED\r
+#define ETIMEDOUT WV_TIMEOUT\r
+#define ENETUNREACH WV_HOST_UNREACHABLE\r
+#define EADDRINUSE WV_ADDRESS_ALREADY_EXISTS\r
+#define EALREADY WV_IO_PENDING\r
+#define EAFNOSUPPORT WV_INVALID_ADDRESS\r
+#define EWOULDBLOCK WV_DEVICE_BUSY\r
+\r
union ibv_gid\r
{\r
uint8_t raw[16];\r
\r
struct ibv_comp_channel\r
{\r
- struct ibv_context *context;\r
- uint32_t timeout;\r
+ struct ibv_context *context;\r
+ COMP_CHANNEL comp_channel;\r
};\r
\r
struct ibv_cq\r
struct ibv_comp_channel *channel;\r
void *cq_context;\r
IWVCompletionQueue *handle;\r
- OVERLAPPED overlap;\r
int cqe;\r
- uint32_t comp_events_completed;\r
+ COMP_ENTRY comp_entry;\r
};\r
\r
struct ibv_ah\r
{\r
struct ibv_device *device;\r
IWVDevice *cmd_if;\r
- uint32_t timeout;\r
+ COMP_CHANNEL channel;\r
};\r
\r
/**\r
__declspec(dllexport)\r
const char *ibv_event_type_str(enum ibv_event_type event);\r
\r
+/*\r
+ * Windows specific structures and interfaces\r
+ */\r
+struct ibv_windata\r
+{\r
+ IWVProvider *prov;\r
+ COMP_MANAGER *comp_mgr;\r
+};\r
+\r
+#define IBV_WINDATA_VERSION 1\r
+\r
+__declspec(dllexport)\r
+int ibv_get_windata(struct ibv_windata *windata, int version);\r
+\r
+__declspec(dllexport)\r
+void ibv_release_windata(struct ibv_windata *windata, int version);\r
+\r
#ifdef __cplusplus\r
}\r
#endif\r
!endif\r
\r
DLLENTRY = DllMain\r
-USE_MSVCRT=1\r
+USE_MSVCRT = 1\r
\r
SOURCES = \\r
ibverbs.rc \\r
#include <stdio.h>\r
#include <infiniband/verbs.h>\r
#include <rdma/winverbs.h>\r
+#include "..\..\..\etc\user\comp_channel.cpp"\r
\r
IWVProvider *prov;\r
+COMP_MANAGER comp_mgr;\r
\r
struct verbs_device\r
{\r
\r
struct verbs_port\r
{\r
- OVERLAPPED overlap;\r
+ COMP_ENTRY comp_entry;\r
DWORD event_flag;\r
+ uint8_t port_num;\r
};\r
\r
-#define EVENT_PORT_NONE 0xFF\r
-\r
struct verbs_context\r
{\r
struct ibv_context context;\r
struct verbs_device device;\r
- HANDLE *event;\r
struct verbs_port *port;\r
- uint8_t event_port_index;\r
+ verbs_port *event_port;\r
};\r
\r
-__declspec(dllexport)\r
-IWVProvider *ibv_get_winverbs(void)\r
+static int ibv_init(void)\r
{\r
HRESULT hr;\r
\r
if (prov == NULL) {\r
hr = WvGetObject(IID_IWVProvider, (LPVOID*) &prov);\r
if (FAILED(hr)) {\r
- return NULL;\r
+ return -1;\r
}\r
+ CompManagerOpen(&comp_mgr);\r
+ CompManagerMonitor(&comp_mgr, prov->GetFileHandle(), 0);\r
+ }\r
+ return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int ibv_get_windata(struct ibv_windata *windata, int version)\r
+{\r
+ int ret;\r
+\r
+ if (version != IBV_WINDATA_VERSION || ibv_init()) {\r
+ return -1;\r
}\r
\r
prov->AddRef();\r
- return prov;\r
+ windata->prov = prov;\r
+ windata->comp_mgr = &comp_mgr;\r
+ return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+void ibv_release_windata(struct ibv_windata *windata, int version)\r
+{\r
+ windata->prov->Release();\r
}\r
\r
__declspec(dllexport)\r
SIZE_T size, cnt;\r
HRESULT hr;\r
\r
- if (prov == NULL) {\r
- hr = WvGetObject(IID_IWVProvider, (LPVOID*) &prov);\r
- if (FAILED(hr)) {\r
- goto err1;\r
- } \r
+ if (ibv_init()) {\r
+ goto err1;\r
}\r
\r
cnt = 0;\r
return NULL;\r
}\r
memcpy(&vcontext->device, vdev, sizeof(struct verbs_device));\r
- vcontext->event_port_index = EVENT_PORT_NONE;\r
- vcontext->context.timeout = INFINITE;\r
+ vcontext->event_port = NULL;\r
+ CompChannelInit(&comp_mgr, &vcontext->context.channel, INFINITE);\r
\r
vcontext->port = new struct verbs_port[vdev->phys_port_cnt];\r
if (vcontext->port == NULL) {\r
goto err1;\r
}\r
\r
- vcontext->event = new HANDLE[vdev->phys_port_cnt];\r
- if (vcontext->event == NULL) {\r
- goto err2;\r
- }\r
-\r
hr = prov->OpenDevice(vdev->guid, &vcontext->context.cmd_if);\r
if (FAILED(hr)) {\r
- goto err3;\r
+ goto err2;\r
}\r
\r
for (i = 0; i < vdev->phys_port_cnt; i++) {\r
- vcontext->event[i] = CreateEvent(NULL, FALSE, FALSE, NULL);\r
- if (vcontext->event[i] == NULL) {\r
- goto err4;\r
- }\r
- vcontext->port[i].overlap.hEvent = vcontext->event[i];\r
+ vcontext->port[i].port_num = (uint8_t) i + 1;\r
vcontext->port[i].event_flag = 0;\r
-\r
- vcontext->context.cmd_if->Notify((UINT8) i + 1,\r
- &vcontext->port[i].overlap,\r
+ CompEntryInit(&vcontext->context.channel, &vcontext->port[i].comp_entry);\r
+ vcontext->context.cmd_if->Notify(vcontext->port[i].port_num,\r
+ &vcontext->port[i].comp_entry.Overlap,\r
&vcontext->port[i].event_flag);\r
}\r
\r
return &vcontext->context;\r
\r
-err4:\r
- while (--i >= 0) {\r
- CloseHandle(vcontext->event[i]);\r
- }\r
-err3:\r
- delete vcontext->event;\r
err2:\r
delete vcontext->port;\r
err1:\r
context->cmd_if->CancelOverlappedRequests();\r
\r
for (i = 0; i < vcontext->device.phys_port_cnt; i++) {\r
- CloseHandle(vcontext->event[i]);\r
+ CompChannelRemoveEntry(&context->channel, &vcontext->port[i].comp_entry);\r
}\r
\r
context->cmd_if->Release();\r
- delete vcontext->event;\r
delete vcontext->port;\r
delete vcontext;\r
return 0;\r
WV_PORT_ATTRIBUTES attr;\r
HRESULT hr;\r
\r
- hr = vcontext->context.cmd_if->QueryPort(vcontext->event_port_index + 1, &attr);\r
+ hr = vcontext->context.cmd_if->QueryPort(vcontext->event_port->port_num, &attr);\r
if (FAILED(hr)) {\r
return IBV_EVENT_PORT_ERR;\r
}\r
struct verbs_port *port;\r
int ret = 0;\r
\r
- port = &vcontext->port[vcontext->event_port_index];\r
- event->element.port_num = vcontext->event_port_index + 1;\r
+ port = vcontext->event_port;\r
+ event->element.port_num = port->port_num;\r
\r
if (port->event_flag & WV_EVENT_ERROR) {\r
event->event_type = IBV_EVENT_DEVICE_FATAL;\r
}\r
\r
if (port->event_flag == 0) {\r
- vcontext->context.cmd_if->Notify(vcontext->event_port_index + 1,\r
- &port->overlap, &port->event_flag);\r
- vcontext->event_port_index = EVENT_PORT_NONE;\r
+ vcontext->context.cmd_if->Notify(vcontext->event_port->port_num,\r
+ &port->comp_entry.Overlap,\r
+ &port->event_flag);\r
+ vcontext->event_port = NULL;\r
}\r
return ret;\r
}\r
struct ibv_async_event *event)\r
{\r
struct verbs_context *vcontext;\r
- HRESULT hr;\r
- int i;\r
+ COMP_ENTRY *entry;\r
+ int ret;\r
\r
vcontext = CONTAINING_RECORD(context, struct verbs_context, context);\r
- if (vcontext->event_port_index != EVENT_PORT_NONE) {\r
+ if (vcontext->event_port) {\r
if (ibv_report_port_event(vcontext, event) == 0) {\r
return 0;\r
}\r
}\r
\r
- hr = WaitForMultipleObjects(vcontext->device.phys_port_cnt,\r
- vcontext->event, FALSE, context->timeout);\r
- if (hr == WAIT_TIMEOUT) {\r
- return hr;\r
- } else if (hr == WAIT_FAILED) {\r
- return HRESULT_FROM_WIN32(GetLastError());\r
+ ret = CompChannelPoll(&context->channel, &entry);\r
+ if (!ret) {\r
+ vcontext->event_port = CONTAINING_RECORD(entry, struct verbs_port, comp_entry);\r
+ ret = ibv_report_port_event(vcontext, event);\r
}\r
\r
- vcontext->event_port_index = (UINT8) hr;\r
- return ibv_report_port_event(vcontext, event);\r
+ return ret;\r
}\r
\r
__declspec(dllexport)\r
ibv_node_type_str\r
ibv_port_state_str\r
ibv_event_type_str\r
+ibv_get_windata\r
+ibv_release_windata\r
#endif\r
/*\r
- * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.\r
- * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.\r
+ * Copyright (c) 2009 Intel Corp, Inc. All rights reserved.\r
*\r
* This software is available to you under the OpenIB.org BSD license\r
* below:\r
#ifndef IB_VERBS_H\r
#define IB_VERBS_H\r
\r
+extern COMP_MANAGER comp_mgr;\r
+\r
__inline void* __cdecl operator new(size_t size)\r
{\r
return HeapAlloc(GetProcessHeap(), 0, size);\r
/*\r
* Copyright (c) 2005 Topspin Communications. All rights reserved.\r
* Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.\r
- * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
+ * Copyright (c) 2008-2009 Intel Corporation. All rights reserved.\r
*\r
* This software is available to you under the OpenIB.org BSD license\r
* below:\r
#include <stdio.h>\r
\r
#include <infiniband/verbs.h>\r
+#include <comp_channel.h>\r
#include "ibverbs.h"\r
\r
-struct verbs_cq\r
-{\r
- struct ibv_cq cq;\r
- int channel_index;\r
-};\r
-\r
-struct verbs_comp_channel\r
-{\r
- struct ibv_comp_channel channel;\r
- CRITICAL_SECTION lock;\r
- struct verbs_cq *cq[MAXIMUM_WAIT_OBJECTS];\r
- HANDLE event[MAXIMUM_WAIT_OBJECTS];\r
- int count;\r
-};\r
-\r
__declspec(dllexport)\r
int ibv_rate_to_mult(enum ibv_rate rate)\r
{\r
case IBV_RATE_60_GBPS: return 24;\r
case IBV_RATE_80_GBPS: return 32;\r
case IBV_RATE_120_GBPS: return 48;\r
- default: return -1;\r
+ default: return -1;\r
}\r
}\r
\r
__declspec(dllexport)\r
struct ibv_comp_channel *ibv_create_comp_channel(struct ibv_context *context)\r
{\r
- struct verbs_comp_channel *vchan;\r
+ struct ibv_comp_channel *channel;\r
\r
- vchan = new struct verbs_comp_channel;\r
- if (vchan == NULL) {\r
+ channel = new struct ibv_comp_channel;\r
+ if (channel == NULL) {\r
return NULL;\r
}\r
\r
- InitializeCriticalSection(&vchan->lock);\r
- vchan->count = 0;\r
- vchan->channel.context = context;\r
- vchan->channel.timeout = INFINITE;\r
-\r
- return &vchan->channel;\r
+ CompChannelInit(&comp_mgr, &channel->comp_channel, INFINITE);\r
+ channel->context = context;\r
+ return channel;\r
}\r
\r
__declspec(dllexport)\r
int ibv_destroy_comp_channel(struct ibv_comp_channel *channel)\r
{\r
- struct verbs_comp_channel *vchan;\r
-\r
- vchan = CONTAINING_RECORD(channel, struct verbs_comp_channel, channel);\r
- if (vchan->count > 0) {\r
- return -1;\r
- }\r
-\r
- DeleteCriticalSection(&vchan->lock); \r
- delete vchan;\r
+ CompChannelCleanup(&channel->comp_channel);\r
+ delete channel;\r
return 0;\r
}\r
\r
-static int ibv_comp_channel_insert_cq(struct ibv_comp_channel *channel,\r
- struct verbs_cq *cq)\r
-{\r
- struct verbs_comp_channel *vchan;\r
- int ret = 0;\r
-\r
- vchan = CONTAINING_RECORD(channel, struct verbs_comp_channel, channel);\r
-\r
- EnterCriticalSection(&vchan->lock);\r
- if (vchan->count == MAXIMUM_WAIT_OBJECTS) {\r
- ret = -1;\r
- goto out;\r
- }\r
-\r
- vchan->cq[vchan->count] = cq;\r
- vchan->event[vchan->count] = cq->cq.overlap.hEvent;\r
- cq->channel_index = vchan->count++;\r
-out:\r
- LeaveCriticalSection(&vchan->lock);\r
- return ret;\r
-}\r
-\r
-/*\r
- * TODO: we cannot call ibv_comp_channel_remove_cq() while another\r
- * thread is calling ibv_get_cq_event(). If this is needed, then we\r
- * need to halt the ibv_get_cq_event() thread, modify the event list,\r
- * then restart the ibv_get_cq_event() thread.\r
- */\r
-static void ibv_comp_channel_remove_cq(struct ibv_comp_channel *channel,\r
- struct verbs_cq *cq)\r
-{\r
- struct verbs_comp_channel *vchan;\r
-\r
- vchan = CONTAINING_RECORD(channel, struct verbs_comp_channel, channel);\r
-\r
- EnterCriticalSection(&vchan->lock);\r
- vchan->count--;\r
- vchan->cq[cq->channel_index] = vchan->cq[vchan->count];\r
- vchan->event[cq->channel_index] = vchan->event[vchan->count];\r
- vchan->cq[cq->channel_index]->channel_index = cq->channel_index;\r
- LeaveCriticalSection(&vchan->lock);\r
-}\r
-\r
__declspec(dllexport)\r
struct ibv_cq *ibv_create_cq(struct ibv_context *context, int cqe, void *cq_context,\r
struct ibv_comp_channel *channel, int comp_vector)\r
{\r
- struct verbs_cq *vcq;\r
+ struct ibv_cq *cq;\r
HRESULT hr;\r
SIZE_T entries;\r
\r
- vcq = new struct verbs_cq;\r
- if (vcq == NULL) {\r
+ cq = new struct ibv_cq;\r
+ if (cq == NULL) {\r
return NULL;\r
}\r
\r
- vcq->cq.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\r
- if (vcq->cq.overlap.hEvent == NULL) {\r
- goto err1;\r
- }\r
-\r
- vcq->cq.context = context;\r
- vcq->cq.channel = channel;\r
- vcq->cq.cq_context = cq_context;\r
- vcq->cq.comp_events_completed = 0;\r
+ cq->context = context;\r
+ cq->channel = channel;\r
+ cq->cq_context = cq_context;\r
\r
entries = cqe;\r
- hr = context->cmd_if->CreateCompletionQueue(&entries, &vcq->cq.handle);\r
+ hr = context->cmd_if->CreateCompletionQueue(&entries, &cq->handle);\r
if (FAILED(hr)) {\r
- goto err2;\r
+ goto err;\r
}\r
\r
if (channel != NULL) {\r
- hr = ibv_comp_channel_insert_cq(channel, vcq);\r
- if (FAILED(hr)) {\r
- goto err3;\r
- }\r
+ CompEntryInit(&channel->comp_channel, &cq->comp_entry);\r
+ } else {\r
+ memset(&cq->comp_entry, 0, sizeof cq->comp_entry);\r
}\r
\r
- vcq->cq.cqe = (uint32_t) entries;\r
- return &vcq->cq;\r
+ cq->cqe = (uint32_t) entries;\r
+ return cq;\r
\r
-err3:\r
- vcq->cq.handle->Release();\r
-err2:\r
- CloseHandle(vcq->cq.overlap.hEvent);\r
-err1:\r
- delete vcq;\r
+err:\r
+ delete cq;\r
return NULL;\r
}\r
\r
int ibv_req_notify_cq(struct ibv_cq *cq, int solicited_only)\r
{\r
HRESULT hr;\r
+\r
hr = cq->handle->Notify(solicited_only ? WvCqSolicited : WvCqNextCompletion,\r
- &cq->overlap);\r
+ &cq->comp_entry.Overlap);\r
if (SUCCEEDED(hr) || hr == WV_IO_PENDING) {\r
return 0;\r
} else {\r
__declspec(dllexport)\r
int ibv_destroy_cq(struct ibv_cq *cq)\r
{\r
- struct verbs_cq *vcq;\r
-\r
- vcq = CONTAINING_RECORD(cq, struct verbs_cq, cq);\r
-\r
cq->handle->CancelOverlappedRequests();\r
\r
if (cq->channel != NULL) {\r
- ibv_comp_channel_remove_cq(cq->channel, vcq);\r
+ CompChannelRemoveEntry(&cq->channel->comp_channel, &cq->comp_entry);\r
}\r
\r
- while (cq->comp_events_completed > 0)\r
- ; /* twiddle thumbs */\r
-\r
cq->handle->Release();\r
delete cq;\r
return 0;\r
int ibv_get_cq_event(struct ibv_comp_channel *channel,\r
struct ibv_cq **cq, void **cq_context)\r
{\r
- struct verbs_comp_channel *vchan;\r
- struct verbs_cq *vcq;\r
- HRESULT hr;\r
+ COMP_ENTRY *entry;\r
+ DWORD ret;\r
\r
- vchan = CONTAINING_RECORD(channel, struct verbs_comp_channel, channel);\r
- hr = WaitForMultipleObjects(vchan->count, vchan->event, FALSE,\r
- vchan->channel.timeout);\r
- if (hr == WAIT_TIMEOUT) {\r
- return hr;\r
- } else if (hr == WAIT_FAILED) {\r
- return HRESULT_FROM_WIN32(GetLastError());\r
+ ret = CompChannelPoll(&channel->comp_channel, &entry);\r
+ if (!ret) {\r
+ *cq = CONTAINING_RECORD(entry, struct ibv_cq, comp_entry);\r
+ *cq_context = (*cq)->cq_context;\r
}\r
\r
- EnterCriticalSection(&vchan->lock);\r
- vcq = vchan->cq[hr];\r
- vcq->cq.comp_events_completed++;\r
- LeaveCriticalSection(&vchan->lock);\r
-\r
- *cq = &vcq->cq;\r
- *cq_context = vcq->cq.cq_context;\r
- return 0;\r
+ return ret;\r
}\r
\r
__declspec(dllexport)\r
void ibv_ack_cq_events(struct ibv_cq *cq, unsigned int nevents)\r
{\r
- struct verbs_comp_channel *vchan;\r
-\r
- if (cq->channel == NULL) {\r
- return;\r
- }\r
-\r
- vchan = CONTAINING_RECORD(cq->channel, struct verbs_comp_channel, channel);\r
- EnterCriticalSection(&vchan->lock);\r
- cq->comp_events_completed -= nevents;\r
- LeaveCriticalSection(&vchan->lock);\r
}\r
\r
__declspec(dllexport)\r