winverbs: process connect and accept asynchronously
authorshefty <shefty@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Tue, 9 Jun 2009 16:40:24 +0000 (16:40 +0000)
committershefty <shefty@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Tue, 9 Jun 2009 16:40:24 +0000 (16:40 +0000)
Allow processing of EP:Connect and EP:Accept calls asynchronously.  The
librdmacm uses events to report the completion of rdma_connect and
rdma_accept calls, which allows users of that interface to take advantage
of asynchronous operation.  Modify the winverbs kernel driver to
queue connect/accept calls to a system thread for better parallelism.

This improves the measured connection rate of rdma_cmatose by 3%.  The
connection rate includes address resolution, route resolution, PD/CQ/QP
creation and state transitions, memory registration, posting of receive
buffers, and CM message exchanges.  This patch effectively only improves
the parallelism of modify QP.

Signed-off-by: Sean Hefty <sean.hefty@intel.com>
git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@2240 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

core/winverbs/kernel/wv_ep.c

index 964cc3b..ab7ef66 100644 (file)
@@ -409,7 +409,6 @@ static NTSTATUS WvEpDisconnectQp(WV_PROVIDER *pProvider, UINT64 QpId,
 \r
 static void WvEpDisconnectHandler(WORK_ENTRY *pWork)\r
 {\r
-       WORK_ENTRY                      *work;\r
        WV_PROVIDER                     *prov;\r
        WDFREQUEST                      request;\r
        WV_IO_EP_DISCONNECT     *pattr;\r
@@ -543,8 +542,10 @@ static NTSTATUS WvEpIbCmHandler(iba_cm_id *pId, iba_cm_event *pEvent)
        return STATUS_SUCCESS;\r
 }\r
 \r
-void WvEpConnect(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+void WvEpConnectHandler(WORK_ENTRY *pWork)\r
 {\r
+       WV_PROVIDER                     *prov;\r
+       WDFREQUEST                      request;\r
        WV_IO_EP_CONNECT        *pattr;\r
        WV_ENDPOINT                     *ep;\r
        WV_QUEUE_PAIR           *qp;\r
@@ -552,7 +553,10 @@ void WvEpConnect(WV_PROVIDER *pProvider, WDFREQUEST Request)
        NTSTATUS                        status;\r
        UINT8                           data[IB_REQ_PDATA_SIZE];\r
 \r
-       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_EP_CONNECT),\r
+       request = (WDFREQUEST) pWork->Context;\r
+       prov = WvProviderGetContext(WdfRequestGetFileObject(request));\r
+\r
+       status = WdfRequestRetrieveInputBuffer(request, sizeof(WV_IO_EP_CONNECT),\r
                                                                                   &pattr, NULL);\r
        if (!NT_SUCCESS(status)) {\r
                goto complete;\r
@@ -563,13 +567,13 @@ void WvEpConnect(WV_PROVIDER *pProvider, WDFREQUEST Request)
                goto complete;\r
        }\r
 \r
-       ep = WvEpAcquire(pProvider, pattr->Id);\r
+       ep = WvEpAcquire(prov, pattr->Id);\r
        if (ep == NULL) {\r
                status = STATUS_NOT_FOUND;\r
                goto complete;\r
        }\r
 \r
-       qp = WvQpAcquire(pProvider, pattr->QpId);\r
+       qp = WvQpAcquire(prov, pattr->QpId);\r
        if (qp == NULL) {\r
                status = STATUS_NOT_FOUND;\r
                goto release;\r
@@ -617,7 +621,7 @@ void WvEpConnect(WV_PROVIDER *pProvider, WDFREQUEST Request)
        ep->State = WvEpActiveConnect;\r
        status = IbCmInterface.CM.send_req(ep->pIbCmId, &req);\r
        if (NT_SUCCESS(status)) {\r
-               status = WdfRequestForwardToIoQueue(Request, ep->Queue);\r
+               status = WdfRequestForwardToIoQueue(request, ep->Queue);\r
        }\r
 \r
        if (!NT_SUCCESS(status)) {\r
@@ -629,10 +633,25 @@ release:
        WvEpRelease(ep);\r
 complete:\r
        if (!NT_SUCCESS(status)) {\r
-               WdfRequestComplete(Request, status);\r
+               WdfRequestComplete(request, status);\r
        }\r
 }\r
 \r
+static void WvEpProcessAsync(WV_PROVIDER *pProvider, WDFREQUEST Request,\r
+                                                        void (*AsyncHandler)(struct _WORK_ENTRY *Work))\r
+{\r
+       WORK_ENTRY      *work;\r
+\r
+       work = WorkEntryFromIrp(WdfRequestWdmGetIrp(Request));\r
+       WorkEntryInit(work, AsyncHandler, Request);\r
+       WorkQueueInsert(&pProvider->WorkQueue, work);\r
+}\r
+\r
+void WvEpConnect(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WvEpProcessAsync(pProvider, Request, WvEpConnectHandler);\r
+}\r
+\r
 static NTSTATUS WvEpModifyQpRtr(WV_ENDPOINT *pEndpoint, WV_QUEUE_PAIR *pQp,\r
                                                                UINT64 ResponderResources, UINT32 Psn,\r
                                                                UINT8 *pVerbsData, UINT32 VerbsSize)\r
@@ -792,21 +811,26 @@ out:
        return status;\r
 }\r
 \r
-void WvEpAccept(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+void WvEpAcceptHandler(WORK_ENTRY *pWork)\r
 {\r
+       WV_PROVIDER                     *prov;\r
+       WDFREQUEST                      request;\r
        WV_IO_EP_ACCEPT         *pattr;\r
        WV_ENDPOINT                     *ep;\r
        NTSTATUS                        status;\r
        UINT8                           *out;\r
        size_t                          outlen;\r
 \r
-       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_EP_ACCEPT),\r
+       request = (WDFREQUEST) pWork->Context;\r
+       prov = WvProviderGetContext(WdfRequestGetFileObject(request));\r
+\r
+       status = WdfRequestRetrieveInputBuffer(request, sizeof(WV_IO_EP_ACCEPT),\r
                                                                                   &pattr, NULL);\r
        if (!NT_SUCCESS(status)) {\r
                goto complete;\r
        }\r
 \r
-       status = WdfRequestRetrieveOutputBuffer(Request, 0, &out, &outlen);\r
+       status = WdfRequestRetrieveOutputBuffer(request, 0, &out, &outlen);\r
        if (!NT_SUCCESS(status) && status != STATUS_BUFFER_TOO_SMALL) {\r
                goto complete;\r
        }\r
@@ -816,7 +840,7 @@ void WvEpAccept(WV_PROVIDER *pProvider, WDFREQUEST Request)
                goto complete;\r
        }\r
 \r
-       ep = WvEpAcquire(pProvider, pattr->Id);\r
+       ep = WvEpAcquire(prov, pattr->Id);\r
        if (ep == NULL) {\r
                status = STATUS_NOT_FOUND;\r
                goto complete;\r
@@ -825,10 +849,10 @@ void WvEpAccept(WV_PROVIDER *pProvider, WDFREQUEST Request)
        /* EP state is re-checked under lock in WvEpAccept* calls */\r
        switch (ep->State) {\r
        case WvEpActiveConnect:\r
-               status = WvEpAcceptActive(Request, out, outlen, ep, pattr);\r
+               status = WvEpAcceptActive(request, out, outlen, ep, pattr);\r
                break;\r
        case WvEpPassiveConnect:\r
-               status = WvEpAcceptPassive(Request, out, outlen, ep, pattr);\r
+               status = WvEpAcceptPassive(request, out, outlen, ep, pattr);\r
                break;\r
        default:\r
                status = STATUS_NOT_SUPPORTED;\r
@@ -838,10 +862,15 @@ void WvEpAccept(WV_PROVIDER *pProvider, WDFREQUEST Request)
        WvEpRelease(ep);\r
 complete:\r
        if (!NT_SUCCESS(status)) {\r
-               WdfRequestComplete(Request, status);\r
+               WdfRequestComplete(request, status);\r
        }\r
 }\r
 \r
+void WvEpAccept(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WvEpProcessAsync(pProvider, Request, WvEpAcceptHandler);\r
+}\r
+\r
 void WvEpReject(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
 {\r
        WV_IO_ID                        *id;\r