]> git.openfabrics.org - ~shefty/rdma-win.git/commitdiff
libibverbs: release reference on WVProvider from ibvw_get_windata
authorSean Hefty <sean.hefty@intel.com>
Thu, 4 Feb 2010 00:54:57 +0000 (16:54 -0800)
committerSean Hefty <sean.hefty@intel.com>
Thu, 4 Feb 2010 00:54:57 +0000 (16:54 -0800)
ibvw_get_windata increments a reference on the global WVProvider.
Release this reference when ibvw_release_windata is called.

Signed-off-by: Sean Hefty <sean.hefty@intel.com>
trunk/ulp/libibverbs/src/device.cpp

index 1b66d3cec912ba71f1831165b29c8406925d39f5..46372bc2b55b2e732ce228c2590ec59c938edcfa 100644 (file)
-/*\r
- * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.\r
- * Copyright (c) 2006, 2007 Cisco Systems, Inc.  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 AWV\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 <stdio.h>\r
-#include <infiniband/verbs.h>\r
-#include <rdma/winverbs.h>\r
-#include "..\..\..\etc\user\comp_channel.cpp"\r
-\r
-CRITICAL_SECTION lock;\r
-IWVProvider *prov;\r
-COMP_MANAGER comp_mgr;\r
-static DWORD ref;\r
-\r
-struct verbs_device\r
-{\r
-       struct ibv_device       device;\r
-       uint64_t                        guid;\r
-       uint8_t                         phys_port_cnt;\r
-};\r
-\r
-struct verbs_port\r
-{\r
-       COMP_ENTRY                      comp_entry;\r
-       DWORD                           event_flag;\r
-       uint8_t                         port_num;\r
-};\r
-\r
-struct verbs_context\r
-{\r
-       struct ibv_context      context;\r
-       struct verbs_device     device;\r
-       uint8_t                         closing;\r
-       struct verbs_port       *port;\r
-       verbs_port                      *event_port;\r
-};\r
-\r
-static int ibv_acquire(void)\r
-{\r
-       HRESULT hr;\r
-\r
-       EnterCriticalSection(&lock);\r
-       if (ref++ == 0) {\r
-               hr = WvGetObject(IID_IWVProvider, (LPVOID*) &prov);\r
-               if (FAILED(hr)) {\r
-                       goto err1;\r
-               }\r
-               hr = CompManagerOpen(&comp_mgr);\r
-               if (FAILED(hr)) {\r
-                       goto err2;\r
-               }\r
-               hr = CompManagerMonitor(&comp_mgr, prov->GetFileHandle(), 0);\r
-               if (FAILED(hr)) {\r
-                       goto err3;\r
-               }\r
-       }\r
-       LeaveCriticalSection(&lock);\r
-       return 0;\r
-\r
-err3:\r
-       CompManagerClose(&comp_mgr);\r
-err2:\r
-       prov->Release();\r
-err1:\r
-       ref--;\r
-       LeaveCriticalSection(&lock);\r
-       return hr;\r
-}\r
-\r
-static void ibv_release(void)\r
-{\r
-       EnterCriticalSection(&lock);\r
-       if (--ref == 0) {\r
-               CompManagerClose(&comp_mgr);\r
-               prov->Release();\r
-       }\r
-       LeaveCriticalSection(&lock);\r
-}\r
-\r
-__declspec(dllexport)\r
-int ibvw_get_windata(struct ibvw_windata *windata, int version)\r
-{\r
-       int ret;\r
-\r
-       if (version != IBVW_WINDATA_VERSION || ibv_acquire()) {\r
-               return -1;\r
-       }\r
-\r
-       prov->AddRef();\r
-       windata->prov = prov;\r
-       windata->comp_mgr = &comp_mgr;\r
-       return 0;\r
-}\r
-\r
-__declspec(dllexport)\r
-void ibvw_release_windata(struct ibvw_windata *windata, int version)\r
-{\r
-       ibv_release();\r
-}\r
-\r
-__declspec(dllexport)\r
-struct ibv_device **ibv_get_device_list(int *num)\r
-{\r
-       WV_DEVICE_ATTRIBUTES attr;\r
-       struct verbs_device *dev_array;\r
-       struct ibv_device **pdev_array;\r
-       NET64 *guid;\r
-       SIZE_T size, cnt;\r
-       HRESULT hr;\r
-\r
-       if (ibv_acquire()) {\r
-               goto err1;\r
-       }\r
-\r
-       cnt = 0;\r
-       size = sizeof(NET64);\r
-\r
-       while ((size / sizeof(NET64)) > cnt) {\r
-               if (cnt > 0) {\r
-                       delete guid;\r
-               }\r
-\r
-               cnt = size / sizeof(NET64);\r
-               guid = new NET64[cnt];\r
-               if (guid == NULL) {\r
-                       goto err1;\r
-               }\r
-\r
-               hr = prov->QueryDeviceList(guid, &size);\r
-               if (FAILED(hr)) {\r
-                       goto err2;\r
-               }\r
-       }\r
-\r
-       size /= sizeof(NET64);\r
-       dev_array = new struct verbs_device[size];\r
-       pdev_array = new struct ibv_device*[size + 1];\r
-       if (dev_array == NULL || pdev_array == NULL) {\r
-               goto err2;\r
-       }\r
-\r
-       for (cnt = 0; cnt < size; cnt++) {\r
-               pdev_array[cnt] = &dev_array[cnt].device;\r
-               hr = prov->QueryDevice(guid[cnt], &attr);\r
-               if (FAILED(hr)) {\r
-                       goto err3;\r
-               }\r
-\r
-               sprintf(dev_array[cnt].device.name, "ibv_device%d", cnt);\r
-               dev_array[cnt].device.node_type = IBV_NODE_UNKNOWN;\r
-               dev_array[cnt].device.transport_type = (ibv_transport_type) attr.DeviceType;\r
-               dev_array[cnt].guid = guid[cnt];\r
-               dev_array[cnt].phys_port_cnt = attr.PhysPortCount;\r
-       }\r
-\r
-       pdev_array[cnt] = NULL;\r
-       if (num != NULL) {\r
-               *num = (int) size;\r
-       }\r
-       return pdev_array;\r
-\r
-err3:\r
-       ibv_free_device_list(pdev_array);\r
-err2:\r
-       delete guid;\r
-err1:\r
-       return NULL;\r
-}\r
-\r
-__declspec(dllexport)\r
-void ibv_free_device_list(struct ibv_device **list)\r
-{\r
-       ibv_release();\r
-       delete CONTAINING_RECORD(list[0], struct verbs_device, device);\r
-       delete list;\r
-}\r
-\r
-__declspec(dllexport)\r
-const char *ibv_get_device_name(struct ibv_device *device)\r
-{\r
-       return device->name;\r
-}\r
-\r
-__declspec(dllexport)\r
-uint64_t ibv_get_device_guid(struct ibv_device *device)\r
-{\r
-       return CONTAINING_RECORD(device, struct verbs_device, device)->guid;\r
-}\r
-\r
-__declspec(dllexport)\r
-struct ibv_context *ibv_open_device(struct ibv_device *device)\r
-{\r
-       struct verbs_device *vdev;\r
-       struct verbs_context *vcontext;\r
-       HRESULT hr;\r
-       int i;\r
-\r
-       vdev = CONTAINING_RECORD(device, struct verbs_device, device);\r
-       vcontext = new struct verbs_context;\r
-       if (vcontext == NULL) {\r
-               return NULL;\r
-       }\r
-\r
-       ibv_acquire();\r
-       memcpy(&vcontext->device, vdev, sizeof(struct verbs_device));\r
-       vcontext->context.device = &vcontext->device.device;\r
-       vcontext->event_port = NULL;\r
-       vcontext->closing = 0;\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
-       hr = prov->OpenDevice(vdev->guid, &vcontext->context.cmd_if);\r
-       if (FAILED(hr)) {\r
-               goto err2;\r
-       }\r
-\r
-       for (i = 0; i < vdev->phys_port_cnt; i++) {\r
-               vcontext->port[i].port_num = (uint8_t) i + 1;\r
-               vcontext->port[i].event_flag = 0;\r
-               CompEntryInit(&vcontext->context.channel, &vcontext->port[i].comp_entry);\r
-               vcontext->port[i].comp_entry.Busy = 1;\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
-err2:\r
-       delete vcontext->port;\r
-err1:\r
-       delete vcontext;\r
-       ibv_release();\r
-       return NULL;\r
-}\r
-\r
-__declspec(dllexport)\r
-int ibv_close_device(struct ibv_context *context)\r
-{\r
-       struct verbs_context *vcontext;\r
-       int i;\r
-\r
-       vcontext = CONTAINING_RECORD(context, struct verbs_context, context);\r
-       vcontext->closing = 1;\r
-       context->cmd_if->CancelOverlappedRequests();\r
-\r
-       for (i = 0; i < vcontext->device.phys_port_cnt; i++) {\r
-               CompEntryCancel(&vcontext->port[i].comp_entry);\r
-       }\r
-\r
-       context->cmd_if->Release();\r
-       CompChannelCleanup(&vcontext->context.channel);\r
-       ibv_release();\r
-       delete vcontext->port;\r
-       delete vcontext;\r
-       return 0;\r
-}\r
-\r
-static enum ibv_event_type ibv_get_port_event_state(struct verbs_context *vcontext)\r
-{\r
-       WV_PORT_ATTRIBUTES attr;\r
-       HRESULT hr;\r
-\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
-\r
-       return (attr.State == WvPortActive) ?\r
-                  IBV_EVENT_PORT_ACTIVE : IBV_EVENT_PORT_ERR;\r
-}\r
-\r
-static int ibv_report_port_event(struct verbs_context *vcontext,\r
-                                                                struct ibv_async_event *event)\r
-{\r
-       struct verbs_port *port;\r
-       int ret = 0;\r
-\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
-               port->event_flag = 0;\r
-       } else if (port->event_flag & WV_EVENT_STATE) {\r
-               event->event_type = ibv_get_port_event_state(vcontext);\r
-               port->event_flag = 0;\r
-       } else if (port->event_flag & WV_EVENT_MANAGEMENT) {\r
-               event->event_type = IBV_EVENT_SM_CHANGE;\r
-               port->event_flag = 0;\r
-       } else if (port->event_flag & WV_EVENT_LINK_ADDRESS) {\r
-               event->event_type = IBV_EVENT_LID_CHANGE;\r
-               port->event_flag &= ~WV_EVENT_LINK_ADDRESS;\r
-       } else if (port->event_flag & WV_EVENT_PARTITION) {\r
-               event->event_type = IBV_EVENT_PKEY_CHANGE;\r
-               port->event_flag &= ~WV_EVENT_PARTITION;\r
-       } else {\r
-               port->event_flag = 0;\r
-               ret = -1;\r
-       }\r
-       \r
-       if (port->event_flag == 0 && !vcontext->closing) {\r
-               port->comp_entry.Busy = 1;\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
-\r
-__declspec(dllexport)\r
-int ibv_get_async_event(struct ibv_context *context,\r
-                                               struct ibv_async_event *event)\r
-{\r
-       struct verbs_context *vcontext;\r
-       COMP_ENTRY *entry;\r
-       int ret;\r
-\r
-       vcontext = CONTAINING_RECORD(context, struct verbs_context, context);\r
-       if (vcontext->event_port) {\r
-               if (ibv_report_port_event(vcontext, event) == 0) {\r
-                       return 0;\r
-               }\r
-       }\r
-\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
-       return ret;\r
-}\r
-\r
-__declspec(dllexport)\r
-void ibv_ack_async_event(struct ibv_async_event *event)\r
-{\r
-       // Only device/port level events are currently supported\r
-       // nothing to do here at the moment\r
-}\r
+/*
+ * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2006, 2007 Cisco Systems, Inc.  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 AWV
+ * 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 <stdio.h>
+#include <infiniband/verbs.h>
+#include <rdma/winverbs.h>
+#include "..\..\..\etc\user\comp_channel.cpp"
+
+CRITICAL_SECTION lock;
+IWVProvider *prov;
+COMP_MANAGER comp_mgr;
+static DWORD ref;
+
+struct verbs_device
+{
+       struct ibv_device       device;
+       uint64_t                        guid;
+       uint8_t                         phys_port_cnt;
+};
+
+struct verbs_port
+{
+       COMP_ENTRY                      comp_entry;
+       DWORD                           event_flag;
+       uint8_t                         port_num;
+};
+
+struct verbs_context
+{
+       struct ibv_context      context;
+       struct verbs_device     device;
+       uint8_t                         closing;
+       struct verbs_port       *port;
+       verbs_port                      *event_port;
+};
+
+static int ibv_acquire(void)
+{
+       HRESULT hr;
+
+       EnterCriticalSection(&lock);
+       if (ref++ == 0) {
+               hr = WvGetObject(IID_IWVProvider, (LPVOID*) &prov);
+               if (FAILED(hr)) {
+                       goto err1;
+               }
+               hr = CompManagerOpen(&comp_mgr);
+               if (FAILED(hr)) {
+                       goto err2;
+               }
+               hr = CompManagerMonitor(&comp_mgr, prov->GetFileHandle(), 0);
+               if (FAILED(hr)) {
+                       goto err3;
+               }
+       }
+       LeaveCriticalSection(&lock);
+       return 0;
+
+err3:
+       CompManagerClose(&comp_mgr);
+err2:
+       prov->Release();
+err1:
+       ref--;
+       LeaveCriticalSection(&lock);
+       return hr;
+}
+
+static void ibv_release(void)
+{
+       EnterCriticalSection(&lock);
+       if (--ref == 0) {
+               CompManagerClose(&comp_mgr);
+               prov->Release();
+       }
+       LeaveCriticalSection(&lock);
+}
+
+__declspec(dllexport)
+int ibvw_get_windata(struct ibvw_windata *windata, int version)
+{
+       int ret;
+
+       if (version != IBVW_WINDATA_VERSION || ibv_acquire()) {
+               return -1;
+       }
+
+       prov->AddRef();
+       windata->prov = prov;
+       windata->comp_mgr = &comp_mgr;
+       return 0;
+}
+
+__declspec(dllexport)
+void ibvw_release_windata(struct ibvw_windata *windata, int version)
+{
+       prov->Release();
+       ibv_release();
+}
+
+__declspec(dllexport)
+struct ibv_device **ibv_get_device_list(int *num)
+{
+       WV_DEVICE_ATTRIBUTES attr;
+       struct verbs_device *dev_array;
+       struct ibv_device **pdev_array;
+       NET64 *guid;
+       SIZE_T size, cnt;
+       HRESULT hr;
+
+       if (ibv_acquire()) {
+               goto err1;
+       }
+
+       cnt = 0;
+       size = sizeof(NET64);
+
+       while ((size / sizeof(NET64)) > cnt) {
+               if (cnt > 0) {
+                       delete guid;
+               }
+
+               cnt = size / sizeof(NET64);
+               guid = new NET64[cnt];
+               if (guid == NULL) {
+                       goto err1;
+               }
+
+               hr = prov->QueryDeviceList(guid, &size);
+               if (FAILED(hr)) {
+                       goto err2;
+               }
+       }
+
+       size /= sizeof(NET64);
+       dev_array = new struct verbs_device[size];
+       pdev_array = new struct ibv_device*[size + 1];
+       if (dev_array == NULL || pdev_array == NULL) {
+               goto err2;
+       }
+
+       for (cnt = 0; cnt < size; cnt++) {
+               pdev_array[cnt] = &dev_array[cnt].device;
+               hr = prov->QueryDevice(guid[cnt], &attr);
+               if (FAILED(hr)) {
+                       goto err3;
+               }
+
+               sprintf(dev_array[cnt].device.name, "ibv_device%d", cnt);
+               dev_array[cnt].device.node_type = IBV_NODE_UNKNOWN;
+               dev_array[cnt].device.transport_type = (ibv_transport_type) attr.DeviceType;
+               dev_array[cnt].guid = guid[cnt];
+               dev_array[cnt].phys_port_cnt = attr.PhysPortCount;
+       }
+
+       pdev_array[cnt] = NULL;
+       if (num != NULL) {
+               *num = (int) size;
+       }
+       return pdev_array;
+
+err3:
+       ibv_free_device_list(pdev_array);
+err2:
+       delete guid;
+err1:
+       return NULL;
+}
+
+__declspec(dllexport)
+void ibv_free_device_list(struct ibv_device **list)
+{
+       ibv_release();
+       delete CONTAINING_RECORD(list[0], struct verbs_device, device);
+       delete list;
+}
+
+__declspec(dllexport)
+const char *ibv_get_device_name(struct ibv_device *device)
+{
+       return device->name;
+}
+
+__declspec(dllexport)
+uint64_t ibv_get_device_guid(struct ibv_device *device)
+{
+       return CONTAINING_RECORD(device, struct verbs_device, device)->guid;
+}
+
+__declspec(dllexport)
+struct ibv_context *ibv_open_device(struct ibv_device *device)
+{
+       struct verbs_device *vdev;
+       struct verbs_context *vcontext;
+       HRESULT hr;
+       int i;
+
+       vdev = CONTAINING_RECORD(device, struct verbs_device, device);
+       vcontext = new struct verbs_context;
+       if (vcontext == NULL) {
+               return NULL;
+       }
+
+       ibv_acquire();
+       memcpy(&vcontext->device, vdev, sizeof(struct verbs_device));
+       vcontext->context.device = &vcontext->device.device;
+       vcontext->event_port = NULL;
+       vcontext->closing = 0;
+       CompChannelInit(&comp_mgr, &vcontext->context.channel, INFINITE);
+
+       vcontext->port = new struct verbs_port[vdev->phys_port_cnt];
+       if (vcontext->port == NULL) {
+               goto err1;
+       }
+
+       hr = prov->OpenDevice(vdev->guid, &vcontext->context.cmd_if);
+       if (FAILED(hr)) {
+               goto err2;
+       }
+
+       for (i = 0; i < vdev->phys_port_cnt; i++) {
+               vcontext->port[i].port_num = (uint8_t) i + 1;
+               vcontext->port[i].event_flag = 0;
+               CompEntryInit(&vcontext->context.channel, &vcontext->port[i].comp_entry);
+               vcontext->port[i].comp_entry.Busy = 1;
+               vcontext->context.cmd_if->Notify(vcontext->port[i].port_num,
+                                                                                &vcontext->port[i].comp_entry.Overlap,
+                                                                                &vcontext->port[i].event_flag);
+       }
+
+       return &vcontext->context;
+
+err2:
+       delete vcontext->port;
+err1:
+       delete vcontext;
+       ibv_release();
+       return NULL;
+}
+
+__declspec(dllexport)
+int ibv_close_device(struct ibv_context *context)
+{
+       struct verbs_context *vcontext;
+       int i;
+
+       vcontext = CONTAINING_RECORD(context, struct verbs_context, context);
+       vcontext->closing = 1;
+       context->cmd_if->CancelOverlappedRequests();
+
+       for (i = 0; i < vcontext->device.phys_port_cnt; i++) {
+               CompEntryCancel(&vcontext->port[i].comp_entry);
+       }
+
+       context->cmd_if->Release();
+       CompChannelCleanup(&vcontext->context.channel);
+       ibv_release();
+       delete vcontext->port;
+       delete vcontext;
+       return 0;
+}
+
+static enum ibv_event_type ibv_get_port_event_state(struct verbs_context *vcontext)
+{
+       WV_PORT_ATTRIBUTES attr;
+       HRESULT hr;
+
+       hr = vcontext->context.cmd_if->QueryPort(vcontext->event_port->port_num, &attr);
+       if (FAILED(hr)) {
+               return IBV_EVENT_PORT_ERR;
+       }
+
+       return (attr.State == WvPortActive) ?
+                  IBV_EVENT_PORT_ACTIVE : IBV_EVENT_PORT_ERR;
+}
+
+static int ibv_report_port_event(struct verbs_context *vcontext,
+                                                                struct ibv_async_event *event)
+{
+       struct verbs_port *port;
+       int ret = 0;
+
+       port = vcontext->event_port;
+       event->element.port_num = port->port_num;
+
+       if (port->event_flag & WV_EVENT_ERROR) {
+               event->event_type = IBV_EVENT_DEVICE_FATAL;
+               port->event_flag = 0;
+       } else if (port->event_flag & WV_EVENT_STATE) {
+               event->event_type = ibv_get_port_event_state(vcontext);
+               port->event_flag = 0;
+       } else if (port->event_flag & WV_EVENT_MANAGEMENT) {
+               event->event_type = IBV_EVENT_SM_CHANGE;
+               port->event_flag = 0;
+       } else if (port->event_flag & WV_EVENT_LINK_ADDRESS) {
+               event->event_type = IBV_EVENT_LID_CHANGE;
+               port->event_flag &= ~WV_EVENT_LINK_ADDRESS;
+       } else if (port->event_flag & WV_EVENT_PARTITION) {
+               event->event_type = IBV_EVENT_PKEY_CHANGE;
+               port->event_flag &= ~WV_EVENT_PARTITION;
+       } else {
+               port->event_flag = 0;
+               ret = -1;
+       }
+       
+       if (port->event_flag == 0 && !vcontext->closing) {
+               port->comp_entry.Busy = 1;
+               vcontext->context.cmd_if->Notify(vcontext->event_port->port_num,
+                                                                                &port->comp_entry.Overlap,
+                                                                                &port->event_flag);
+               vcontext->event_port = NULL;
+       }
+       return ret;
+}
+
+__declspec(dllexport)
+int ibv_get_async_event(struct ibv_context *context,
+                                               struct ibv_async_event *event)
+{
+       struct verbs_context *vcontext;
+       COMP_ENTRY *entry;
+       int ret;
+
+       vcontext = CONTAINING_RECORD(context, struct verbs_context, context);
+       if (vcontext->event_port) {
+               if (ibv_report_port_event(vcontext, event) == 0) {
+                       return 0;
+               }
+       }
+
+       ret = CompChannelPoll(&context->channel, &entry);
+       if (!ret) {
+               vcontext->event_port = CONTAINING_RECORD(entry, struct verbs_port, comp_entry);
+               ret = ibv_report_port_event(vcontext, event);
+       }
+
+       return ret;
+}
+
+__declspec(dllexport)
+void ibv_ack_async_event(struct ibv_async_event *event)
+{
+       // Only device/port level events are currently supported
+       // nothing to do here at the moment
+}