]> git.openfabrics.org - ~shefty/rdma-win.git/commitdiff
delete
authorSean Hefty <sean.hefty@intel.com>
Thu, 18 Feb 2010 22:25:00 +0000 (14:25 -0800)
committerSean Hefty <sean.hefty@intel.com>
Thu, 18 Feb 2010 22:25:00 +0000 (14:25 -0800)
meta
patches/old-apphang [deleted file]

diff --git a/meta b/meta
index 6105883b0c8ccc9c048d17630f8c46b10761fc5a..b495b64e5d0741adfaf63096837ad87b9ea0f5a3 100644 (file)
--- a/meta
+++ b/meta
@@ -1,5 +1,5 @@
 Version: 1
-Previous: 56a652ce80085eea22def7eb1980e4c00b13ce91
+Previous: b19adc1979ff1228a56b287a9eac195be2f28ef2
 Head: dfe9e20feb196aac78ebbda4c4c8d0221c8d27fa
 Applied:
   rm-build: dfe9e20feb196aac78ebbda4c4c8d0221c8d27fa
@@ -21,7 +21,6 @@ Unapplied:
   test-pkey0: 812ba9c5ccb0e841f37bdc52713151bd4175613e
   test-nd-times: 7b3cb2057aee2bf0853a0fbc89d76624ab5a10c0
   test-sync-wv: 0fb4fbfa8b43dd13ae43922001092f6bd24811c9
-  old-apphang: 7a6f7ff02c6035e54fc262414eb9484ea98018b9
   old-cm_send_cb: 70dceed7518c8429e4c9e0646c7ec035f1cf53cb
   old-queue_mads: a9c572c34ae693764a33e87173125d3065a6d1c5
 Hidden:
diff --git a/patches/old-apphang b/patches/old-apphang
deleted file mode 100644 (file)
index 09d7af6..0000000
+++ /dev/null
@@ -1,657 +0,0 @@
-Bottom: 6a0d87b4622bc7319d396436b319ad51c6ae3636
-Top:    ed7908e04b3bbaa4e2413f01b2efe982eb5349d8
-Author: U-AMR\MSHEFTY <MSHEFTY@mshefty-MOBL2.amr.corp.intel.com>
-Date:   2009-12-09 17:26:01 -0800
-
-KMDF tracks all requests that pass through an IO queue.  Even after a
-request has been removed from the queue, the request still maintains a
-reference on the queue.  Any attempt to delete the queue will block
-until all requests holding references on the queue have completed.
-
-To avoid deadlock conditions during cleanup, we need to ensure that
-all requests can complete during cleanup.  Modify the asynchronous
-handling code to queue a separate data structure, so that all requests
-can remain on the IO queues.
-
-Signed-off-by: Sean Hefty <sean.hefty@intel.com>
-
-
----
-
-diff --git a/trunk/core/winverbs/kernel/wv_ep.c b/trunk/core/winverbs/kernel/wv_ep.c
-index 2fbb5b3..3d5c6ce 100644
---- a/trunk/core/winverbs/kernel/wv_ep.c
-+++ b/trunk/core/winverbs/kernel/wv_ep.c
-@@ -38,6 +38,8 @@
- #define WV_AF_INET    2\r
- #define WV_AF_INET6   23\r
\r
-+static void WvEpWorkHandler(WORK_ENTRY *pWork);\r
-+\r
- static void WvEpGet(WV_ENDPOINT *pEndpoint)\r
- {\r
-       InterlockedIncrement(&pEndpoint->Ref);\r
-@@ -87,6 +89,12 @@ static NTSTATUS WvEpAllocate(WV_PROVIDER *pProvider, UINT16 EpType,
-       }\r
\r
-       RtlZeroMemory(ep, sizeof(WV_ENDPOINT));\r
-+      ep->pWork = ExAllocatePoolWithTag(NonPagedPool, sizeof(WV_WORK_ENTRY), 'wevw');\r
-+      if (ep->pWork == NULL) {\r
-+              status = STATUS_NO_MEMORY;\r
-+              goto err1;\r
-+      }\r
-+\r
-       ep->Ref = 1;\r
-       ep->pProvider = pProvider;\r
-       ep->EpType = EpType;\r
-@@ -97,13 +105,15 @@ static NTSTATUS WvEpAllocate(WV_PROVIDER *pProvider, UINT16 EpType,
-       status = WdfIoQueueCreate(ControlDevice, &config,\r
-                                                         WDF_NO_OBJECT_ATTRIBUTES, &ep->Queue);\r
-       if (!NT_SUCCESS(status)) {\r
--              goto err;\r
-+              goto err2;\r
-       }\r
\r
-       *ppEndpoint = ep;\r
-       return STATUS_SUCCESS;\r
\r
--err:\r
-+err2:\r
-+      ExFreePoolWithTag(ep->pWork, 'wevw');\r
-+err1:\r
-       ExFreePoolWithTag(ep, 'pevw');\r
-       return status;\r
- }\r
-@@ -137,6 +147,7 @@ void WvEpCreate(WV_PROVIDER *pProvider, WDFREQUEST Request)
-       }\r
-       KeReleaseGuardedMutex(&pProvider->Lock);\r
\r
-+      WvWorkEntryInit(ep->pWork, *pId, WvEpWorkHandler, pProvider);\r
-       WdfRequestCompleteWithInformation(Request, status, sizeof(UINT64));\r
-       return;\r
\r
-@@ -195,6 +206,9 @@ void WvEpFree(WV_ENDPOINT *pEndpoint)
\r
-       WdfIoQueuePurgeSynchronously(pEndpoint->Queue);\r
-       WdfObjectDelete(pEndpoint->Queue);\r
-+      if (pEndpoint->pWork != NULL) {\r
-+              ExFreePoolWithTag(pEndpoint->pWork, 'wevw');\r
-+      }\r
-       ExFreePoolWithTag(pEndpoint, 'pevw');\r
- }\r
\r
-@@ -413,77 +427,72 @@ static NTSTATUS WvEpDisconnectQp(WV_PROVIDER *pProvider, UINT64 QpId,
-       return status;\r
- }\r
\r
--static void WvEpDisconnectHandler(WORK_ENTRY *pWork)\r
-+static NTSTATUS WvEpAsyncDisconnect(WV_ENDPOINT *pEndpoint, WDFREQUEST Request)\r
- {\r
--      WV_PROVIDER                     *prov;\r
--      WDFREQUEST                      request;\r
-       WV_IO_EP_DISCONNECT     *pattr;\r
-       UINT8                           *out;\r
-       size_t                          outlen = 0;\r
-       NTSTATUS                        status;\r
\r
--      request = (WDFREQUEST) pWork->Context;\r
--      prov = WvProviderGetContext(WdfRequestGetFileObject(request));\r
--\r
--      status = WdfRequestRetrieveInputBuffer(request, sizeof(WV_IO_EP_DISCONNECT),\r
-+      status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_EP_DISCONNECT),\r
-                                                                                  &pattr, NULL);\r
-       if (!NT_SUCCESS(status)) {\r
--              goto complete;\r
-+              return status;\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
-+              return status;\r
-       }\r
\r
--      status = (NTSTATUS) WdfRequestGetInformation(request);\r
-+      status = (NTSTATUS) WdfRequestGetInformation(Request);\r
-       if (NT_SUCCESS(status)) {\r
--              status = WvEpDisconnectQp(prov, pattr->QpId, out, outlen);\r
-+              status = WvEpDisconnectQp(pEndpoint->pProvider, pattr->QpId, out, outlen);\r
-       } else {\r
--              WvEpDisconnectQp(prov, pattr->QpId, out, outlen);\r
-+              WvEpDisconnectQp(pEndpoint->pProvider, pattr->QpId, out, outlen);\r
-       }\r
\r
--complete:\r
--      WdfRequestCompleteWithInformation(request, status, outlen);\r
--      WvProviderPut(prov);\r
-+      WdfRequestCompleteWithInformation(Request, status, outlen);\r
-+      return STATUS_SUCCESS;\r
- }\r
\r
--// We use IRP DriverContext to queue the request for further processing,\r
--// but the request/IRP are no longer owned by the framework.\r
- static void WvEpCompleteDisconnect(WV_ENDPOINT *pEndpoint, NTSTATUS DiscStatus)\r
- {\r
-       WDFREQUEST                              request;\r
-+      WDFREQUEST                              disc_req = NULL;\r
-       WDF_REQUEST_PARAMETERS  param;\r
--      WORK_ENTRY                              *work;\r
-       NTSTATUS                                status;\r
\r
-       WdfObjectAcquireLock(pEndpoint->Queue);\r
--      if (pEndpoint->State == WvEpDestroying) {\r
-+      if (pEndpoint->State == WvEpDestroying || !pEndpoint->pWork) {\r
-               goto release;\r
-       }\r
-       pEndpoint->State = WvEpDisconnected;\r
\r
-       status = WdfIoQueueRetrieveNextRequest(pEndpoint->Queue, &request);\r
-       while (NT_SUCCESS(status)) {\r
--              WdfObjectReleaseLock(pEndpoint->Queue);\r
\r
-               WDF_REQUEST_PARAMETERS_INIT(&param);\r
-               WdfRequestGetParameters(request, &param);\r
-               if (param.Parameters.DeviceIoControl.IoControlCode == WV_IOCTL_EP_DISCONNECT) {\r
--                      work = WorkEntryFromIrp(WdfRequestWdmGetIrp(request));\r
-                       WdfRequestSetInformation(request, DiscStatus);\r
--                      WorkEntryInit(work, WvEpDisconnectHandler, request);\r
-                       WvProviderGet(pEndpoint->pProvider);\r
--                      WorkQueueInsert(&pEndpoint->pProvider->WorkQueue, work);\r
-+                      WorkQueueInsert(&pEndpoint->pProvider->WorkQueue, &pEndpoint->pWork->Work);\r
-+                      pEndpoint->pWork = NULL;\r
-+                      disc_req = request;\r
-               } else {\r
-                       WdfRequestComplete(request, DiscStatus);\r
-               }\r
\r
--              WdfObjectAcquireLock(pEndpoint->Queue);\r
-               status = WdfIoQueueRetrieveNextRequest(pEndpoint->Queue, &request);\r
-       }\r
-+\r
-+      if (disc_req != NULL) {\r
-+              WdfRequestRequeue(disc_req);\r
-+      }\r
- release:\r
-       WdfObjectReleaseLock(pEndpoint->Queue);\r
-+\r
- }\r
\r
- static NTSTATUS WvEpIbCmHandler(iba_cm_id *pId, iba_cm_event *pEvent)\r
-@@ -565,49 +574,31 @@ static NTSTATUS WvEpIbCmHandler(iba_cm_id *pId, iba_cm_event *pEvent)
-       return STATUS_SUCCESS;\r
- }\r
\r
--void WvEpConnectHandler(WORK_ENTRY *pWork)\r
-+static NTSTATUS WvEpAsyncConnect(WV_ENDPOINT *pEndpoint, WDFREQUEST Request)\r
- {\r
--      WV_PROVIDER                     *prov;\r
--      WDFREQUEST                      request;\r
-       WV_IO_EP_CONNECT        *pattr;\r
--      WV_ENDPOINT                     *ep;\r
-       WV_QUEUE_PAIR           *qp;\r
-       iba_cm_req                      req;\r
-       NTSTATUS                        status;\r
-       UINT8                           data[IB_REQ_PDATA_SIZE];\r
\r
--      request = (WDFREQUEST) pWork->Context;\r
--      prov = WvProviderGetContext(WdfRequestGetFileObject(request));\r
--\r
--      status = WdfRequestRetrieveInputBuffer(request, sizeof(WV_IO_EP_CONNECT),\r
-+      status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_EP_CONNECT),\r
-                                                                                  &pattr, NULL);\r
-       if (!NT_SUCCESS(status)) {\r
--              goto complete;\r
--      }\r
--\r
--      if (pattr->Param.DataLength > sizeof(pattr->Param.Data)) {\r
--              status = STATUS_INVALID_BUFFER_SIZE;\r
--              goto complete;\r
--      }\r
--\r
--      ep = WvEpAcquire(prov, pattr->Id);\r
--      if (ep == NULL) {\r
--              status = STATUS_NOT_FOUND;\r
--              goto complete;\r
-+              return status;\r
-       }\r
\r
--      qp = WvQpAcquire(prov, pattr->QpId);\r
-+      qp = WvQpAcquire(pEndpoint->pProvider, pattr->QpId);\r
-       if (qp == NULL) {\r
--              status = STATUS_NOT_FOUND;\r
--              goto release;\r
-+              return STATUS_NOT_FOUND;\r
-       }\r
\r
--      ep->Attributes.PeerAddress = pattr->PeerAddress;\r
--      WvFormatCmaHeader((IB_CMA_HEADER *) data, &ep->Attributes.LocalAddress,\r
--                                        &ep->Attributes.PeerAddress);\r
-+      pEndpoint->Attributes.PeerAddress = pattr->PeerAddress;\r
-+      WvFormatCmaHeader((IB_CMA_HEADER *) data, &pEndpoint->Attributes.LocalAddress,\r
-+                                        &pEndpoint->Attributes.PeerAddress);\r
\r
--      req.service_id = WvGetServiceId(ep->EpType, &ep->Attributes.PeerAddress);\r
--      req.p_primary_path = &ep->Route;\r
-+      req.service_id = WvGetServiceId(pEndpoint->EpType, &pEndpoint->Attributes.PeerAddress);\r
-+      req.p_primary_path = &pEndpoint->Route;\r
-       req.p_alt_path = NULL;\r
-       req.qpn = qp->Qpn;\r
-       req.qp_type = IB_QPT_RELIABLE_CONN;\r
-@@ -627,54 +618,86 @@ void WvEpConnectHandler(WORK_ENTRY *pWork)
-       req.srq = (qp->pSrq != NULL);\r
\r
-       WvQpRelease(qp);\r
--      RtlCopyMemory(&ep->Attributes.Param.Connect, &pattr->Param,\r
-+      RtlCopyMemory(&pEndpoint->Attributes.Param.Connect, &pattr->Param,\r
-                                 sizeof(pattr->Param));\r
\r
--      WdfObjectAcquireLock(ep->Queue);\r
--      if (ep->State != WvEpRouteResolved) {\r
-+      WdfObjectAcquireLock(pEndpoint->Queue);\r
-+      if (pEndpoint->State != WvEpRouteResolved) {\r
-               status = STATUS_NOT_SUPPORTED;\r
--              goto unlock;\r
-+              goto out;\r
-       }\r
\r
--      status = IbCmInterface.CM.create_id(WvEpIbCmHandler, ep, &ep->pIbCmId);\r
-+      status = IbCmInterface.CM.create_id(WvEpIbCmHandler, pEndpoint, &pEndpoint->pIbCmId);\r
-       if (!NT_SUCCESS(status)) {\r
--              goto unlock;\r
-+              goto out;\r
-       }\r
\r
--      ep->State = WvEpActiveConnect;\r
--      status = IbCmInterface.CM.send_req(ep->pIbCmId, &req);\r
-+      pEndpoint->State = WvEpActiveConnect;\r
-+      status = IbCmInterface.CM.send_req(pEndpoint->pIbCmId, &req);\r
-       if (NT_SUCCESS(status)) {\r
--              status = WdfRequestForwardToIoQueue(request, ep->Queue);\r
-+              status = WdfRequestRequeue(Request);\r
-       }\r
\r
-       if (!NT_SUCCESS(status)) {\r
--              ep->State = WvEpDisconnected;\r
--      }\r
--unlock:\r
--      WdfObjectReleaseLock(ep->Queue);\r
--release:\r
--      WvEpRelease(ep);\r
--complete:\r
--      if (!NT_SUCCESS(status)) {\r
--              WdfRequestComplete(request, status);\r
-+              pEndpoint->State = WvEpDisconnected;\r
-       }\r
--      WvProviderPut(prov);\r
-+\r
-+out:\r
-+      WdfObjectReleaseLock(pEndpoint->Queue);\r
-+      return status;\r
- }\r
\r
--static void WvEpProcessAsync(WV_PROVIDER *pProvider, WDFREQUEST Request,\r
--                                                       void (*AsyncHandler)(struct _WORK_ENTRY *Work))\r
-+static NTSTATUS WvEpProcessAsync(WV_PROVIDER *pProvider, UINT64 Id, WDFREQUEST Request)\r
- {\r
--      WORK_ENTRY      *work;\r
-+      WV_ENDPOINT     *ep;\r
-+      NTSTATUS        status;\r
-+\r
-+      ep = WvEpAcquire(pProvider, Id);\r
-+      if (ep == NULL) {\r
-+              return STATUS_NOT_FOUND;\r
-+      }\r
-+\r
-+      WdfObjectAcquireLock(ep->Queue);\r
-+      if (!ep->pWork) {\r
-+              status = STATUS_TOO_MANY_COMMANDS;\r
-+              goto out;\r
-+      }\r
\r
--      work = WorkEntryFromIrp(WdfRequestWdmGetIrp(Request));\r
--      WorkEntryInit(work, AsyncHandler, Request);\r
--      WvProviderGet(pProvider);\r
--      WorkQueueInsert(&pProvider->WorkQueue, work);\r
-+      status = WdfRequestForwardToIoQueue(Request, ep->Queue);\r
-+      if (NT_SUCCESS(status)) {\r
-+              WvProviderGet(pProvider);\r
-+              WorkQueueInsert(&pProvider->WorkQueue, &ep->pWork->Work);\r
-+              ep->pWork = NULL;\r
-+      }\r
-+\r
-+out:\r
-+      WdfObjectReleaseLock(ep->Queue);\r
-+      WvEpRelease(ep);\r
-+      return status;\r
- }\r
\r
- void WvEpConnect(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
- {\r
--      WvEpProcessAsync(pProvider, Request, WvEpConnectHandler);\r
-+      WV_IO_EP_CONNECT        *pattr;\r
-+      NTSTATUS                        status;\r
-+\r
-+      status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_EP_CONNECT),\r
-+                                                                                 &pattr, NULL);\r
-+      if (!NT_SUCCESS(status)) {\r
-+              goto out;\r
-+      }\r
-+\r
-+      if (pattr->Param.DataLength > sizeof(pattr->Param.Data)) {\r
-+              status = STATUS_INVALID_BUFFER_SIZE;\r
-+              goto out;\r
-+      }\r
-+\r
-+      status = WvEpProcessAsync(pProvider, pattr->Id, Request);\r
-+\r
-+out:\r
-+      if (!NT_SUCCESS(status)) {\r
-+              WdfRequestComplete(Request, status);\r
-+      }\r
- }\r
\r
- static NTSTATUS WvEpModifyQpRtr(WV_ENDPOINT *pEndpoint, WV_QUEUE_PAIR *pQp,\r
-@@ -823,7 +846,7 @@ static NTSTATUS WvEpAcceptPassive(WDFREQUEST Request, UINT8 *pVerbsData, size_t
\r
-       status = IbCmInterface.CM.send_rep(pEndpoint->pIbCmId, &rep);\r
-       if (NT_SUCCESS(status)) {\r
--              status = WdfRequestForwardToIoQueue(Request, pEndpoint->Queue);\r
-+              status = WdfRequestRequeue(Request);\r
-       }\r
-       \r
-       if (!NT_SUCCESS(status)) {\r
-@@ -836,65 +859,114 @@ out:
-       return status;\r
- }\r
\r
--void WvEpAcceptHandler(WORK_ENTRY *pWork)\r
-+static NTSTATUS WvEpAsyncAccept(WV_ENDPOINT *pEndpoint, WDFREQUEST Request)\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
--      request = (WDFREQUEST) pWork->Context;\r
--      prov = WvProviderGetContext(WdfRequestGetFileObject(request));\r
--\r
--      status = WdfRequestRetrieveInputBuffer(request, sizeof(WV_IO_EP_ACCEPT),\r
-+      status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_EP_ACCEPT),\r
-                                                                                  &pattr, NULL);\r
-       if (!NT_SUCCESS(status)) {\r
--              goto complete;\r
-+              return status;\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
--\r
--      if (pattr->Param.DataLength > sizeof(pattr->Param.Data)) {\r
--              status = STATUS_INVALID_BUFFER_SIZE;\r
--              goto complete;\r
--      }\r
--\r
--      ep = WvEpAcquire(prov, pattr->Id);\r
--      if (ep == NULL) {\r
--              status = STATUS_NOT_FOUND;\r
--              goto complete;\r
-+              return status;\r
-       }\r
\r
-       /* EP state is re-checked under lock in WvEpAccept* calls */\r
--      switch (ep->State) {\r
-+      switch (pEndpoint->State) {\r
-       case WvEpActiveConnect:\r
--              status = WvEpAcceptActive(request, out, outlen, ep, pattr);\r
-+              status = WvEpAcceptActive(Request, out, outlen, pEndpoint, pattr);\r
-               break;\r
-       case WvEpPassiveConnect:\r
--              status = WvEpAcceptPassive(request, out, outlen, ep, pattr);\r
-+              status = WvEpAcceptPassive(Request, out, outlen, pEndpoint, pattr);\r
-               break;\r
-       default:\r
-               status = STATUS_NOT_SUPPORTED;\r
-               break;\r
-       }\r
\r
--      WvEpRelease(ep);\r
--complete:\r
-+      return status;\r
-+}\r
-+\r
-+static void WvEpWorkHandler(WORK_ENTRY *pWork)\r
-+{\r
-+      WV_PROVIDER                             *prov;\r
-+      WV_ENDPOINT                             *ep;\r
-+      WV_WORK_ENTRY                   *work;\r
-+      WDFREQUEST                              request;\r
-+      WDF_REQUEST_PARAMETERS  param;\r
-+      NTSTATUS                                status;\r
-+\r
-+      work = CONTAINING_RECORD(pWork, WV_WORK_ENTRY, Work);\r
-+      prov = (WV_PROVIDER *) pWork->Context;\r
-+\r
-+      ep = WvEpAcquire(prov, work->Id);\r
-+      if (ep == NULL) {\r
-+              ExFreePoolWithTag(work, 'wevw');\r
-+              goto out;\r
-+      }\r
-+\r
-+      WdfObjectAcquireLock(ep->Queue);\r
-+      ep->pWork = work;\r
-+      status = WdfIoQueueRetrieveNextRequest(ep->Queue, &request);\r
-+      WdfObjectReleaseLock(ep->Queue);\r
-+\r
-+      if (!NT_SUCCESS(status)) {\r
-+              goto put;\r
-+      }\r
-+\r
-+      WDF_REQUEST_PARAMETERS_INIT(&param);\r
-+      WdfRequestGetParameters(request, &param);\r
-+      switch (param.Parameters.DeviceIoControl.IoControlCode) {\r
-+      case WV_IOCTL_EP_CONNECT:\r
-+              status = WvEpAsyncConnect(ep, request);\r
-+              break;\r
-+      case WV_IOCTL_EP_ACCEPT:\r
-+              status = WvEpAsyncAccept(ep, request);\r
-+              break;\r
-+      case WV_IOCTL_EP_DISCONNECT:\r
-+              status = WvEpAsyncDisconnect(ep, request);\r
-+              break;\r
-+      default:\r
-+              status = STATUS_NOT_IMPLEMENTED;\r
-+      }\r
-+\r
-       if (!NT_SUCCESS(status)) {\r
-               WdfRequestComplete(request, status);\r
-       }\r
-+put:\r
-+      WvEpRelease(ep);\r
-+out:\r
-       WvProviderPut(prov);\r
- }\r
\r
- void WvEpAccept(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
- {\r
--      WvEpProcessAsync(pProvider, Request, WvEpAcceptHandler);\r
-+      WV_IO_EP_ACCEPT         *pattr;\r
-+      NTSTATUS                        status;\r
-+\r
-+      status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_EP_ACCEPT),\r
-+                                                                                 &pattr, NULL);\r
-+      if (!NT_SUCCESS(status)) {\r
-+              goto out;\r
-+      }\r
-+\r
-+      if (pattr->Param.DataLength > sizeof(pattr->Param.Data)) {\r
-+              status = STATUS_INVALID_BUFFER_SIZE;\r
-+              goto out;\r
-+      }\r
-+\r
-+      status = WvEpProcessAsync(pProvider, pattr->Id, Request);\r
-+\r
-+out:\r
-+      if (!NT_SUCCESS(status)) {\r
-+              WdfRequestComplete(Request, status);\r
-+      }\r
- }\r
\r
- void WvEpReject(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
-@@ -932,69 +1004,7 @@ complete:
-       WdfRequestComplete(Request, status);\r
- }\r
\r
--static NTSTATUS WvEpDisconnectActive(WDFREQUEST Request,\r
--                                                                       UINT8 *pVerbsData, size_t VerbsSize,\r
--                                                                       WV_ENDPOINT *pEndpoint,\r
--                                                                       WV_IO_EP_DISCONNECT *pAttr)\r
--{\r
--      NTSTATUS status, failure;\r
--\r
--      WdfObjectAcquireLock(pEndpoint->Queue);\r
--      if (pEndpoint->State != WvEpConnected) {\r
--              status = STATUS_NOT_SUPPORTED;\r
--              goto release;\r
--      }\r
--\r
--      pEndpoint->State = WvEpActiveDisconnect;\r
--      IbCmInterface.CM.send_dreq(pEndpoint->pIbCmId, NULL, 0);\r
--\r
--      status = WdfRequestForwardToIoQueue(Request, pEndpoint->Queue);\r
--      if (!NT_SUCCESS(status)) {\r
--              pEndpoint->State = WvEpDisconnected;\r
--              WvCompleteRequests(pEndpoint->Queue, STATUS_UNSUCCESSFUL);\r
--              WdfObjectReleaseLock(pEndpoint->Queue);\r
--\r
--              failure = status;\r
--              status = WvEpDisconnectQp(pEndpoint->pProvider, pAttr->QpId,\r
--                                                                pVerbsData, VerbsSize);\r
--              if (NT_SUCCESS(status)) {\r
--                      WdfRequestCompleteWithInformation(Request, failure, VerbsSize);\r
--              }\r
--              return status;\r
--      }\r
--\r
--release:\r
--      WdfObjectReleaseLock(pEndpoint->Queue);\r
--      return status;\r
--}\r
--\r
--static NTSTATUS WvEpDisconnectPassive(WDFREQUEST Request,\r
--                                                                        UINT8 *pVerbsData, size_t VerbsSize,\r
--                                                                        WV_ENDPOINT *pEndpoint,\r
--                                                                        WV_IO_EP_DISCONNECT *pAttr)\r
--{\r
--      NTSTATUS status;\r
--\r
--      WdfObjectAcquireLock(pEndpoint->Queue);\r
--      if (pEndpoint->State != WvEpPassiveDisconnect) {\r
--              WdfObjectReleaseLock(pEndpoint->Queue);\r
--              return STATUS_NOT_SUPPORTED;\r
--      }\r
--\r
--      pEndpoint->State = WvEpDisconnected;\r
--      WdfObjectReleaseLock(pEndpoint->Queue);\r
--\r
--      IbCmInterface.CM.send_drep(pEndpoint->pIbCmId, NULL, 0);\r
--\r
--      status = WvEpDisconnectQp(pEndpoint->pProvider, pAttr->QpId,\r
--                                                        pVerbsData, VerbsSize);\r
--      if (NT_SUCCESS(status)) {\r
--              WdfRequestCompleteWithInformation(Request, status, VerbsSize);\r
--      }\r
--\r
--      return status;\r
--}\r
--\r
-+// The IB CM could have received and processed a DREQ that we haven't seen yet.\r
- void WvEpDisconnect(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
- {\r
-       WV_IO_EP_DISCONNECT     *pattr;\r
-@@ -1020,19 +1030,36 @@ void WvEpDisconnect(WV_PROVIDER *pProvider, WDFREQUEST Request)
-               goto complete;\r
-       }\r
\r
--      /* EP state is re-checked under lock in WvEpDisconnect* calls */\r
-+      WdfObjectAcquireLock(ep->Queue);\r
-       switch (ep->State) {\r
-       case WvEpConnected:\r
--              status = WvEpDisconnectActive(Request, out, outlen, ep, pattr);\r
--              break;\r
-+              status = IbCmInterface.CM.send_dreq(ep->pIbCmId, NULL, 0);\r
-+              if (NT_SUCCESS(status)) {\r
-+                      status = WdfRequestForwardToIoQueue(Request, ep->Queue);\r
-+                      if (NT_SUCCESS(status)) {\r
-+                              ep->State = WvEpActiveDisconnect;\r
-+                              break;\r
-+                      }\r
-+              }\r
-+              /* Fall through to passive disconnect case on failure */\r
-       case WvEpPassiveDisconnect:\r
--              status = WvEpDisconnectPassive(Request, out, outlen, ep, pattr);\r
--              break;\r
-+              ep->State = WvEpDisconnected;\r
-+              WdfObjectReleaseLock(ep->Queue);\r
-+\r
-+              IbCmInterface.CM.send_drep(ep->pIbCmId, NULL, 0);\r
-+\r
-+              status = WvEpDisconnectQp(ep->pProvider, pattr->QpId, out, outlen);\r
-+              if (NT_SUCCESS(status)) {\r
-+                      WdfRequestCompleteWithInformation(Request, status, outlen);\r
-+              }\r
-+              goto release;\r
-       default:\r
--              status = STATUS_NOT_SUPPORTED;\r
-+              status = STATUS_INVALID_DEVICE_STATE;\r
-               break;\r
-       }\r
-+      WdfObjectReleaseLock(ep->Queue);\r
\r
-+release:\r
-       WvEpRelease(ep);\r
- complete:\r
-       if (!NT_SUCCESS(status)) {\r
-diff --git a/trunk/core/winverbs/kernel/wv_ep.h b/trunk/core/winverbs/kernel/wv_ep.h
-index f6d48d3..650b23c 100644
---- a/trunk/core/winverbs/kernel/wv_ep.h
-+++ b/trunk/core/winverbs/kernel/wv_ep.h
-@@ -72,6 +72,7 @@ typedef struct _WV_ENDPOINT
-       KEVENT                          Event;\r
-       LONG                            Ref;\r
-       WDFQUEUE                        Queue;\r
-+      WV_WORK_ENTRY           *pWork;\r
\r
- }     WV_ENDPOINT;\r
\r
-diff --git a/trunk/core/winverbs/kernel/wv_provider.h b/trunk/core/winverbs/kernel/wv_provider.h
-index 329145f..bd430fb 100644
---- a/trunk/core/winverbs/kernel/wv_provider.h
-+++ b/trunk/core/winverbs/kernel/wv_provider.h
-@@ -44,6 +44,20 @@
- struct _WV_DEVICE;\r
- struct _WV_PROTECTION_DOMAIN;\r
\r
-+typedef struct _WV_WORK_ENTRY\r
-+{\r
-+      WORK_ENTRY              Work;\r
-+      UINT64                  Id;\r
-+\r
-+}     WV_WORK_ENTRY;\r
-+\r
-+static void WvWorkEntryInit(WV_WORK_ENTRY *pWork, UINT64 Id,\r
-+                                                      void (*WorkHandler)(WORK_ENTRY *Work), void *Context)\r
-+{\r
-+      pWork->Id = Id;\r
-+      WorkEntryInit(&pWork->Work, WorkHandler, Context);\r
-+}\r
-+\r
- typedef struct _WV_PROVIDER\r
- {\r
-       LIST_ENTRY              Entry;