]> git.openfabrics.org - ~shefty/rdma-win.git/commitdiff
refresh (create temporary patch)
authorU-AMR\MSHEFTY <MSHEFTY@mshefty-MOBL2.amr.corp.intel.com>
Mon, 14 Dec 2009 18:47:27 +0000 (10:47 -0800)
committerU-AMR\MSHEFTY <MSHEFTY@mshefty-MOBL2.amr.corp.intel.com>
Mon, 14 Dec 2009 18:47:27 +0000 (10:47 -0800)
meta
patches/refresh-temp [new file with mode: 0644]

diff --git a/meta b/meta
index 26900baa1c2cd8ab8563fd7a95118cf1bde215f4..718d92befbe5733dcdfd8d39bdd50de9f3beb626 100644 (file)
--- a/meta
+++ b/meta
@@ -1,10 +1,11 @@
 Version: 1
-Previous: a098e6c59a292fc95366e17c102b066d51865113
-Head: c3e80737f5bfa7c1ca8a3746a118a1579e32dbf6
+Previous: 472620803a0c558fb2a5df1bc0e4983b2d9d93bd
+Head: 802113576c989f23c607e1a90cfde4e198e2f940
 Applied:
   rm-build: 4a07738a3e31c0b254263c5aac316c086b1eafce
   epdisc: 4c931f6af5e37a502f7a10b78a902747f9738623
   debug: 7fcfbb36cb831bda7f290662ca81daf212c5fc1a
   apphang: c3e80737f5bfa7c1ca8a3746a118a1579e32dbf6
+  refresh-temp: 802113576c989f23c607e1a90cfde4e198e2f940
 Unapplied:
 Hidden:
diff --git a/patches/refresh-temp b/patches/refresh-temp
new file mode 100644 (file)
index 0000000..894b954
--- /dev/null
@@ -0,0 +1,590 @@
+Bottom: 8c27f84cff39a377773253e8b126c5a856075319
+Top:    e4242dd87b5ae269806c6f97c8ff402c0a47dcd6
+Author: U-AMR\MSHEFTY <MSHEFTY@mshefty-MOBL2.amr.corp.intel.com>
+Date:   2009-12-14 10:47:24 -0800
+
+Refresh of apphang
+
+---
+
+diff --git a/trunk/core/winmad/kernel/wm_provider.c b/trunk/core/winmad/kernel/wm_provider.c
+index d1d2eec..a150bf1 100644
+--- a/trunk/core/winmad/kernel/wm_provider.c
++++ b/trunk/core/winmad/kernel/wm_provider.c
+@@ -127,7 +127,7 @@ void WmProviderCleanup(WM_PROVIDER *pProvider)
+               KeWaitForSingleObject(&pProvider->Event, Executive, KernelMode, FALSE, NULL);\r
+       }\r
\r
+-      WdfIoQueuePurge(pProvider->ReadQueue, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT);\r
++      WdfIoQueuePurgeSynchronously(pProvider->ReadQueue);\r
+       WdfObjectDelete(pProvider->ReadQueue);\r
\r
+       IndexListDestroy(&pProvider->RegIndex);\r
+diff --git a/trunk/core/winverbs/kernel/wv_cq.c b/trunk/core/winverbs/kernel/wv_cq.c
+index 181a215..76e79db 100644
+--- a/trunk/core/winverbs/kernel/wv_cq.c
++++ b/trunk/core/winverbs/kernel/wv_cq.c
+@@ -230,8 +230,8 @@ void WvCqFree(WV_COMPLETION_QUEUE *pCq)
+               pCq->pVerbs->destroy_cq(pCq->hVerbsCq);\r
+       }\r
\r
+-      WdfIoQueuePurge(pCq->Queue, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT);\r
+-      WdfIoQueuePurge(pCq->ErrorQueue, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT);\r
++      WdfIoQueuePurgeSynchronously(pCq->Queue);\r
++      WdfIoQueuePurgeSynchronously(pCq->ErrorQueue);\r
+       WdfObjectDelete(pCq->Queue);\r
+       WdfObjectDelete(pCq->ErrorQueue);\r
+       WvDevicePut(pCq->pDevice);\r
+diff --git a/trunk/core/winverbs/kernel/wv_device.c b/trunk/core/winverbs/kernel/wv_device.c
+index 4a91a6d..3175011 100644
+--- a/trunk/core/winverbs/kernel/wv_device.c
++++ b/trunk/core/winverbs/kernel/wv_device.c
+@@ -364,7 +364,7 @@ static void WvDeviceFreePorts(WV_DEVICE *pDevice)
+       UINT8 i;\r
\r
+       for (i = 0; i < pDevice->PortCount; i++) {\r
+-              WdfIoQueuePurge(pDevice->pPorts[i].Queue, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT);\r
++              WdfIoQueuePurgeSynchronously(pDevice->pPorts[i].Queue);\r
+               WdfObjectDelete(pDevice->pPorts[i].Queue);\r
+       }\r
+       if (pDevice->pPorts != NULL) {\r
+diff --git a/trunk/core/winverbs/kernel/wv_ep.c b/trunk/core/winverbs/kernel/wv_ep.c
+index e9a01aa..c4031ac 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
+@@ -202,8 +213,11 @@ void WvEpFree(WV_ENDPOINT *pEndpoint)
+               IbCmInterface.CM.destroy_id(pEndpoint->pIbCmId);\r
+       }\r
\r
+-      WdfIoQueuePurge(pEndpoint->Queue, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT);\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
+@@ -422,77 +436,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
+@@ -574,49 +583,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
+@@ -636,54 +627,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
+-      work = WorkEntryFromIrp(WdfRequestWdmGetIrp(Request));\r
+-      WorkEntryInit(work, AsyncHandler, Request);\r
+-      WvProviderGet(pProvider);\r
+-      WorkQueueInsert(&pProvider->WorkQueue, work);\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
++      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
+@@ -832,7 +855,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
+@@ -845,65 +868,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
+-              WdfRequestComplete(request, 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_NOT_IMPLEMENTED);\r
++      }\r
++put:\r
++      WvEpPut(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
+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;\r
+diff --git a/trunk/core/winverbs/kernel/wv_srq.c b/trunk/core/winverbs/kernel/wv_srq.c
+index 21878e5..99f2b49 100644
+--- a/trunk/core/winverbs/kernel/wv_srq.c
++++ b/trunk/core/winverbs/kernel/wv_srq.c
+@@ -236,7 +236,7 @@ void WvSrqFree(WV_SHARED_RECEIVE_QUEUE *pSrq)
+               pSrq->pVerbs->destroy_srq(pSrq->hVerbsSrq);\r
+       }\r
\r
+-      WdfIoQueuePurge(pSrq->Queue, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT);\r
++      WdfIoQueuePurgeSynchronously(pSrq->Queue);\r
+       WdfObjectDelete(pSrq->Queue);\r
+       WvPdPut(pSrq->pPd);\r
+       ExFreePoolWithTag(pSrq, 'rsvw');