libibverbs: use comp_channel to enhance scalability
[mirror/winof/.git] / ulp / libibverbs / src / device.cpp
index af63338..58a2ec5 100644 (file)
 #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
@@ -43,35 +45,53 @@ struct verbs_device
 \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
@@ -84,11 +104,8 @@ struct ibv_device **ibv_get_device_list(int *num)
        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
@@ -179,45 +196,30 @@ struct ibv_context *ibv_open_device(struct ibv_device *device)
                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
@@ -235,11 +237,10 @@ int ibv_close_device(struct ibv_context *context)
        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
@@ -250,7 +251,7 @@ static enum ibv_event_type ibv_get_port_event_state(struct verbs_context *vconte
        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
@@ -265,8 +266,8 @@ static int ibv_report_port_event(struct verbs_context *vcontext,
        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
@@ -289,9 +290,10 @@ static int ibv_report_port_event(struct verbs_context *vcontext,
        }\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
@@ -301,26 +303,23 @@ int ibv_get_async_event(struct ibv_context *context,
                                                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