Forgot to add wv_ep.c. Add it now!
authorshefty <shefty@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Sat, 24 Jan 2009 19:46:05 +0000 (19:46 +0000)
committershefty <shefty@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Sat, 24 Jan 2009 19:46:05 +0000 (19:46 +0000)
Signed-off-by: Sean Hefty <sean.hefty@intel.com>
git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@1876 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

core/winverbs/kernel/wv_ep.c [new file with mode: 0644]

diff --git a/core/winverbs/kernel/wv_ep.c b/core/winverbs/kernel/wv_ep.c
new file mode 100644 (file)
index 0000000..6b28848
--- /dev/null
@@ -0,0 +1,1096 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation. 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 <ntifs.h>\r
+#include <iba/ib_rdma_cm.h>\r
+\r
+#include "wv_ep.h"\r
+#include "wv_qp.h"\r
+#include "wv_ioctl.h"\r
+#include "wv_driver.h"\r
+\r
+#define WV_AF_INET     2\r
+#define WV_AF_INET6    23\r
+\r
+static void WvEpGet(WV_ENDPOINT *pEndpoint)\r
+{\r
+       InterlockedIncrement(&pEndpoint->Ref);\r
+}\r
+\r
+static void WvEpPut(WV_ENDPOINT *pEndpoint)\r
+{\r
+       if (InterlockedDecrement(&pEndpoint->Ref) == 0) {\r
+               KeSetEvent(&pEndpoint->Event, 0, FALSE);\r
+       }\r
+}\r
+\r
+WV_ENDPOINT *WvEpAcquire(WV_PROVIDER *pProvider, UINT64 Id)\r
+{\r
+       WV_ENDPOINT *ep;\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       WvProviderDisableRemove(pProvider);\r
+       ep = IndexListAt(&pProvider->EpIndex, (SIZE_T) Id);\r
+       if (ep != NULL) {\r
+               WvEpGet(ep);\r
+       } else {\r
+               ep = NULL;\r
+               WvProviderEnableRemove(pProvider);\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       return ep;\r
+}\r
+\r
+void WvEpRelease(WV_ENDPOINT *pEndpoint)\r
+{\r
+       WvProviderEnableRemove(pEndpoint->pProvider);\r
+       WvEpPut(pEndpoint);\r
+}\r
+\r
+static NTSTATUS WvEpAllocate(WV_PROVIDER *pProvider, UINT16 EpType,\r
+                                                        WV_ENDPOINT **ppEndpoint)\r
+{\r
+       WV_ENDPOINT                     *ep;\r
+       NTSTATUS                        status;\r
+       WDF_IO_QUEUE_CONFIG     config;\r
+\r
+       ep = ExAllocatePoolWithTag(NonPagedPool, sizeof(WV_ENDPOINT), 'pevw');\r
+       if (ep == NULL) {\r
+               return STATUS_NO_MEMORY;\r
+       }\r
+\r
+       RtlZeroMemory(ep, sizeof(WV_ENDPOINT));\r
+       ep->Ref = 1;\r
+       ep->pProvider = pProvider;\r
+       ep->EpType = EpType;\r
+       KeInitializeEvent(&ep->Event, NotificationEvent, FALSE);\r
+       InitializeListHead(&ep->Entry);\r
+\r
+       WDF_IO_QUEUE_CONFIG_INIT(&config, WdfIoQueueDispatchManual);\r
+       status = WdfIoQueueCreate(ControlDevice, &config,\r
+                                                         WDF_NO_OBJECT_ATTRIBUTES, &ep->Queue);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err;\r
+       }\r
+\r
+       *ppEndpoint = ep;\r
+       return STATUS_SUCCESS;\r
+\r
+err:\r
+       ExFreePool(ep);\r
+       return status;\r
+}\r
+\r
+void WvEpCreate(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UINT64                          *pId;\r
+       UINT64                          *type;\r
+       WV_ENDPOINT                     *ep;\r
+       NTSTATUS                        status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &type, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(UINT64), &pId, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+\r
+       status = WvEpAllocate(pProvider, (UINT16) *type, &ep);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       *pId = IndexListInsertHead(&pProvider->EpIndex, ep);\r
+       if (*pId == 0) {\r
+               status = STATUS_NO_MEMORY;\r
+               goto err2;\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       WdfRequestCompleteWithInformation(Request, status, sizeof(UINT64));\r
+       return;\r
+\r
+err2:\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+       WvEpFree(ep);\r
+err1:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvEpDestroy(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_ENDPOINT             *ep;\r
+       UINT64                  *id;\r
+       NTSTATUS                status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       WvProviderDisableRemove(pProvider);\r
+       ep = IndexListAt(&pProvider->EpIndex, (SIZE_T) *id);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+       } else if (ep->Ref > 1) {\r
+               status = STATUS_ACCESS_DENIED;\r
+       } else {\r
+               IndexListRemove(&pProvider->EpIndex, (SIZE_T) *id);\r
+               status = STATUS_SUCCESS;\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       if (NT_SUCCESS(status)) {\r
+               WvEpFree(ep);\r
+       }\r
+       WvProviderEnableRemove(pProvider);\r
+out:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvEpFree(WV_ENDPOINT *pEndpoint)\r
+{\r
+       if (pEndpoint->pIbCmId != NULL) {\r
+               IbCmInterface.CM.destroy_id(pEndpoint->pIbCmId);\r
+       }\r
+\r
+       if (InterlockedDecrement(&pEndpoint->Ref) > 0) {\r
+               KeWaitForSingleObject(&pEndpoint->Event, Executive, KernelMode, FALSE, NULL);\r
+       }\r
+\r
+       WdfIoQueuePurgeSynchronously(pEndpoint->Queue);\r
+       WdfObjectDelete(pEndpoint->Queue);\r
+       ExFreePool(pEndpoint);\r
+}\r
+\r
+void WvEpQuery(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UINT64                          *id;\r
+       WV_IO_EP_ATTRIBUTES     *pattr;\r
+       WV_ENDPOINT                     *ep;\r
+       size_t                          len = 0;\r
+       NTSTATUS                        status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_EP_ATTRIBUTES),\r
+                                                                                       &pattr, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       ep = WvEpAcquire(pProvider, *id);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       *pattr = ep->Attributes;\r
+       WvEpRelease(ep);\r
+       len = sizeof(WV_IO_EP_ATTRIBUTES);\r
+\r
+complete:\r
+       WdfRequestCompleteWithInformation(Request, status, len);\r
+}\r
+\r
+void WvEpModify(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_ID                                *pId;\r
+       size_t                                  inlen;\r
+       WV_ENDPOINT                             *ep;\r
+       NTSTATUS                                status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_ID), &pId, &inlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       if (pId->Data != WV_IO_EP_OPTION_ROUTE) {\r
+               status = STATUS_INVALID_PARAMETER;\r
+               goto complete;\r
+       }\r
+\r
+       if (inlen < sizeof(WV_IO_ID) + sizeof(ib_path_rec_t)) {\r
+               status = STATUS_BUFFER_TOO_SMALL;\r
+               goto complete;\r
+       }\r
+\r
+       ep = WvEpAcquire(pProvider, pId->Id);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       WdfObjectAcquireLock(ep->Queue);\r
+       if (ep->State != WvEpAddressBound) {\r
+               status = STATUS_NOT_SUPPORTED;\r
+               goto release;\r
+       }\r
+\r
+       RtlCopyMemory(&ep->Route, pId + 1, sizeof ep->Route);\r
+       ep->State = WvEpRouteResolved;\r
+\r
+release:\r
+       WdfObjectReleaseLock(ep->Queue);\r
+       WvEpRelease(ep);\r
+complete:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvEpBind(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_EP_BIND           *pattr;\r
+       WV_ENDPOINT                     *ep;\r
+       size_t                          len = 0;\r
+       NTSTATUS                        status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_EP_BIND),\r
+                                                                                  &pattr, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_EP_BIND),\r
+                                                                                       &pattr, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       ep = WvEpAcquire(pProvider, pattr->Id);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       WdfObjectAcquireLock(ep->Queue);\r
+       if (ep->State != WvEpIdle) {\r
+               status = STATUS_NOT_SUPPORTED;\r
+               goto release;\r
+       }\r
+\r
+       ep->Attributes.LocalAddress = pattr->Address;\r
+       ep->Attributes.Device = pattr->Device;\r
+       len = sizeof(WV_IO_EP_BIND);\r
+       ep->State = WvEpAddressBound;\r
+\r
+release:\r
+       WdfObjectReleaseLock(ep->Queue);\r
+       WvEpRelease(ep);\r
+complete:\r
+       WdfRequestCompleteWithInformation(Request, status, len);\r
+}\r
+\r
+static UINT64 WvGetServiceId(UINT16 EpType, WV_IO_SOCKADDR_DATA *pAddress)\r
+{\r
+       return RtlUlonglongByteSwap(((UINT64)EpType << 16) +\r
+                  RtlUshortByteSwap(pAddress->SockAddr.In.SinPort));\r
+}\r
+\r
+static int WvAnyAddress(WV_IO_SOCKADDR_DATA *pAddress)\r
+{\r
+       if (pAddress->SockAddr.Sa.SaFamily == WV_AF_INET) {\r
+               return (pAddress->SockAddr.In.SinAddr == 0) ||\r
+                          ((pAddress->SockAddr.In.SinAddr & 0xff) == 0x7f);\r
+       } else {\r
+               return (RtlCompareMemoryUlong(pAddress->SockAddr.In6.Sin6Addr, 16, 0) == 16);\r
+       }\r
+}\r
+\r
+static void WvFormatCmaHeader(IB_CMA_HEADER *pHeader,\r
+                                                         WV_IO_SOCKADDR_DATA *pLocalAddress,\r
+                                                         WV_IO_SOCKADDR_DATA *pPeerAddress)\r
+{\r
+       pHeader->CmaVersion = IB_CMA_VERSION;\r
+       if (pLocalAddress->SockAddr.Sa.SaFamily == WV_AF_INET) {\r
+               pHeader->IpVersion = 4 << 4;\r
+               pHeader->SrcAddress.Ip4.Address = pLocalAddress->SockAddr.In.SinAddr;\r
+               pHeader->DstAddress.Ip4.Address = pPeerAddress->SockAddr.In.SinAddr;\r
+               pHeader->Port = pLocalAddress->SockAddr.In.SinPort;\r
+       } else {\r
+               pHeader->IpVersion = 6 << 4;\r
+               RtlCopyMemory(pHeader->SrcAddress.Ip6Address,\r
+                                         pLocalAddress->SockAddr.In6.Sin6Addr, 16);\r
+               RtlCopyMemory(pHeader->DstAddress.Ip6Address,\r
+                                         pPeerAddress->SockAddr.In6.Sin6Addr, 16);\r
+               pHeader->Port = pLocalAddress->SockAddr.In6.Sin6Port;\r
+       }\r
+}\r
+\r
+static void WvEpSaveReply(WV_ENDPOINT *pEndpoint, iba_cm_rep_event *pReply)\r
+{\r
+       UINT8   len;\r
+\r
+       len = sizeof(pEndpoint->Attributes.Param.Connect.Data);\r
+       RtlCopyMemory(pEndpoint->Attributes.Param.Connect.Data, pReply->rep.p_pdata, len);\r
+       pEndpoint->Attributes.Param.Connect.DataLength = len;\r
+       pEndpoint->Attributes.Param.Connect.InitiatorDepth = pReply->rep.resp_res;\r
+       pEndpoint->Attributes.Param.Connect.ResponderResources = pReply->rep.init_depth;\r
+       pEndpoint->Attributes.Param.Connect.RnrRetryCount = pReply->rep.rnr_retry_cnt;\r
+}\r
+\r
+static void WvEpSaveReject(WV_ENDPOINT *pEndpoint, iba_cm_rej_event *pReject)\r
+{\r
+       UINT8   len;\r
+\r
+       len = sizeof(pEndpoint->Attributes.Param.Connect.Data);\r
+       RtlCopyMemory(pEndpoint->Attributes.Param.Connect.Data, pReject->p_pdata, len);\r
+       pEndpoint->Attributes.Param.Connect.DataLength = len;\r
+}\r
+\r
+static NTSTATUS WvEpIbCmHandler(iba_cm_id *pId, iba_cm_event *pEvent)\r
+{\r
+       WV_ENDPOINT     *ep;\r
+\r
+       ep = pId->context;\r
+       switch (pEvent->type) {\r
+       case iba_cm_req_error:\r
+       case iba_cm_rep_error:\r
+       case iba_cm_dreq_error:\r
+               WdfObjectAcquireLock(ep->Queue);\r
+               ep->State = WvEpDisconnected;\r
+               WvCompleteRequests(ep->Queue, STATUS_IO_TIMEOUT);\r
+               WdfObjectReleaseLock(ep->Queue);\r
+               break;\r
+       case iba_cm_rep_received:\r
+               WdfObjectAcquireLock(ep->Queue);\r
+               if (ep->State == WvEpActiveConnect) {\r
+                       WvEpSaveReply(ep, &pEvent->data.rep);\r
+                       WvCompleteRequests(ep->Queue, STATUS_SUCCESS);\r
+               }\r
+               WdfObjectReleaseLock(ep->Queue);\r
+               break;\r
+       case iba_cm_rtu_received:\r
+               WdfObjectAcquireLock(ep->Queue);\r
+               if (ep->State == WvEpPassiveConnect) {\r
+                       WvCompleteRequestsWithInformation(ep->Queue, STATUS_SUCCESS);\r
+                       ep->State = WvEpConnected;\r
+               }\r
+               WdfObjectReleaseLock(ep->Queue);\r
+               break;\r
+       case iba_cm_dreq_received:\r
+               WdfObjectAcquireLock(ep->Queue);\r
+               if (ep->State == WvEpConnected) {\r
+                       ep->State = WvEpPassiveDisconnect;\r
+               } else {\r
+                       ep->State = WvEpDisconnected;\r
+                       IbCmInterface.CM.send_drep(pId, NULL, 0);\r
+               }\r
+               WvCompleteRequests(ep->Queue, STATUS_CONNECTION_DISCONNECTED);\r
+               WdfObjectReleaseLock(ep->Queue);\r
+               break;\r
+       case iba_cm_drep_received:\r
+               WdfObjectAcquireLock(ep->Queue);\r
+               ep->State = WvEpDisconnected;\r
+               WvCompleteRequests(ep->Queue, STATUS_CONNECTION_DISCONNECTED);\r
+               WdfObjectReleaseLock(ep->Queue);\r
+               break;\r
+       case iba_cm_rej_received:\r
+               WdfObjectAcquireLock(ep->Queue);\r
+               if (ep->State == WvEpPassiveConnect || ep->State == WvEpActiveConnect) {\r
+                       ep->State = WvEpDisconnected;\r
+                       WvEpSaveReject(ep, &pEvent->data.rej);\r
+                       WvCompleteRequests(ep->Queue, STATUS_REQUEST_NOT_ACCEPTED);\r
+               }\r
+               WdfObjectReleaseLock(ep->Queue);\r
+               break;\r
+       case iba_cm_mra_received:\r
+               break;\r
+       default:\r
+               WdfObjectAcquireLock(ep->Queue);\r
+               ep->State = WvEpDisconnected;\r
+               WvCompleteRequests(ep->Queue, STATUS_NOT_IMPLEMENTED);\r
+               WdfObjectReleaseLock(ep->Queue);\r
+               break;\r
+       }\r
+\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+void WvEpConnect(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\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
+       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(pProvider, pattr->Id);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       qp = WvQpAcquire(pProvider, pattr->QpId);\r
+       if (qp == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto release;\r
+       }\r
+\r
+       ep->Attributes.PeerAddress = pattr->PeerAddress;\r
+       WvFormatCmaHeader((IB_CMA_HEADER *) data, &ep->Attributes.LocalAddress,\r
+                                         &ep->Attributes.PeerAddress);\r
+\r
+       req.service_id = WvGetServiceId(ep->EpType, &ep->Attributes.PeerAddress);\r
+       req.p_primary_path = &ep->Route;\r
+       req.p_alt_path = NULL;\r
+       req.qpn = qp->Qpn;\r
+       req.qp_type = IB_QPT_RELIABLE_CONN;\r
+       req.starting_psn = (net32_t) RtlRandomEx(&RandomSeed);\r
+       req.p_pdata = data;\r
+       RtlCopyMemory(data + sizeof(IB_CMA_HEADER), pattr->Param.Data,\r
+                                 pattr->Param.DataLength);\r
+       req.pdata_len = sizeof(IB_CMA_HEADER) + pattr->Param.DataLength;\r
+       req.max_cm_retries = IB_CMA_MAX_CM_RETRIES;\r
+       req.resp_res = (UINT8) pattr->Param.ResponderResources;\r
+       req.init_depth = (UINT8) pattr->Param.InitiatorDepth;\r
+       req.remote_resp_timeout = IB_CMA_CM_RESPONSE_TIMEOUT;\r
+       req.flow_ctrl = 1;\r
+       req.local_resp_timeout = IB_CMA_CM_RESPONSE_TIMEOUT;\r
+       req.rnr_retry_cnt = pattr->Param.RnrRetryCount;\r
+       req.retry_cnt = pattr->Param.RetryCount;\r
+       req.srq = (qp->pSrq != NULL);\r
+\r
+       WvQpRelease(qp);\r
+       RtlCopyMemory(&ep->Attributes.Param.Connect, &pattr->Param,\r
+                                 sizeof(pattr->Param));\r
+\r
+       WdfObjectAcquireLock(ep->Queue);\r
+       if (ep->State != WvEpRouteResolved) {\r
+               status = STATUS_NOT_SUPPORTED;\r
+               goto release;\r
+       }\r
+\r
+       status = IbCmInterface.CM.create_id(WvEpIbCmHandler, ep, &ep->pIbCmId);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto release;\r
+       }\r
+\r
+       ep->State = WvEpActiveConnect;\r
+       status = WdfRequestForwardToIoQueue(Request, ep->Queue);\r
+       if (NT_SUCCESS(status)) {\r
+               status = IbCmInterface.CM.send_req(ep->pIbCmId, &req);\r
+       }\r
+\r
+       if (!NT_SUCCESS(status)) {\r
+               ep->State = WvEpDisconnected;\r
+       }\r
+release:\r
+       WdfObjectReleaseLock(ep->Queue);\r
+       WvEpRelease(ep);\r
+complete:\r
+       if (!NT_SUCCESS(status)) {\r
+               WdfRequestComplete(Request, status);\r
+       }\r
+}\r
+\r
+static NTSTATUS WvEpModifyQpRtr(WV_ENDPOINT *pEndpoint, WV_QUEUE_PAIR *pQp,\r
+                                                               UINT64 ResponderResources, UINT32 Psn,\r
+                                                               UINT8 *pVerbsData, UINT32 VerbsSize)\r
+{\r
+       ib_qp_mod_t                     attr;\r
+       ib_api_status_t         ib_status;\r
+       NTSTATUS                        status;\r
+\r
+       status =IbCmInterface.CM.get_qp_attr(pEndpoint->pIbCmId, IB_QPS_INIT, &attr);\r
+       if (!NT_SUCCESS(status)) {\r
+               return status;\r
+       }\r
+       \r
+       ib_status = pQp->pVerbs->ndi_modify_qp(pQp->hVerbsQp, &attr, NULL,\r
+                                                                                  VerbsSize, pVerbsData);\r
+       if (ib_status != IB_SUCCESS) {\r
+               return STATUS_UNSUCCESSFUL;\r
+       }\r
+\r
+       status = IbCmInterface.CM.get_qp_attr(pEndpoint->pIbCmId, IB_QPS_RTR, &attr);\r
+       if (!NT_SUCCESS(status)) {\r
+               return status;\r
+       }\r
+       \r
+       if (pEndpoint->State == WvEpPassiveConnect) {\r
+               attr.state.rtr.resp_res = (UINT8) ResponderResources;\r
+               attr.state.rtr.rq_psn = Psn;\r
+       }\r
+\r
+       ib_status = pQp->pVerbs->ndi_modify_qp(pQp->hVerbsQp, &attr, NULL,\r
+                                                                                  VerbsSize, pVerbsData);\r
+       if (ib_status != IB_SUCCESS) {\r
+               return STATUS_UNSUCCESSFUL;\r
+       }\r
+\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+static NTSTATUS WvEpModifyQpRts(WV_ENDPOINT *pEndpoint, WV_QUEUE_PAIR *pQp,\r
+                                                               UINT64 InitiatorDepth,\r
+                                                               UINT8 *pVerbsData, UINT32 VerbsSize)\r
+{\r
+       ib_qp_mod_t                     attr;\r
+       ib_api_status_t         ib_status;\r
+       NTSTATUS                        status;\r
+\r
+       status = IbCmInterface.CM.get_qp_attr(pEndpoint->pIbCmId, IB_QPS_RTS, &attr);\r
+       if (!NT_SUCCESS(status)) {\r
+               return status;\r
+       }\r
+       \r
+       if (pEndpoint->State == WvEpPassiveConnect) {\r
+               attr.state.rts.init_depth = (UINT8) InitiatorDepth;\r
+       }\r
+\r
+       ib_status = pQp->pVerbs->ndi_modify_qp(pQp->hVerbsQp, &attr, NULL,\r
+                                                                                  VerbsSize, pVerbsData);\r
+       if (ib_status != IB_SUCCESS) {\r
+               return STATUS_UNSUCCESSFUL;\r
+       }\r
+\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+static NTSTATUS WvEpAcceptActive(WDFREQUEST Request, UINT8 *pVerbsData, size_t VerbsSize,\r
+                                                                WV_ENDPOINT *pEndpoint, WV_IO_EP_ACCEPT *pAttr)\r
+{\r
+       WV_QUEUE_PAIR           *qp;\r
+       NTSTATUS                        status;\r
+\r
+       qp = WvQpAcquire(pEndpoint->pProvider, pAttr->QpId);\r
+       if (qp == NULL) {\r
+               return STATUS_NOT_FOUND;\r
+       }\r
+\r
+       status = WvEpModifyQpRtr(pEndpoint, qp, 0, 0, pVerbsData, VerbsSize);\r
+       if (NT_SUCCESS(status)) {\r
+               status = WvEpModifyQpRts(pEndpoint, qp, 0, pVerbsData, VerbsSize);\r
+       }\r
+\r
+       WvQpRelease(qp);\r
+\r
+       WdfObjectAcquireLock(pEndpoint->Queue);\r
+       if (pEndpoint->State != WvEpActiveConnect) {\r
+               status = STATUS_NOT_SUPPORTED;\r
+               goto release;\r
+       }\r
+\r
+       pEndpoint->State = WvEpConnected;\r
+       status = IbCmInterface.CM.send_rtu(pEndpoint->pIbCmId, pAttr->Param.Data,\r
+                                                                          pAttr->Param.DataLength);\r
+       if (NT_SUCCESS(status)) {\r
+               WdfRequestComplete(Request, STATUS_SUCCESS);\r
+       } else {\r
+               pEndpoint->State = WvEpDisconnected;\r
+       }\r
+\r
+release:\r
+       WdfObjectReleaseLock(pEndpoint->Queue);\r
+       return status;\r
+}\r
+\r
+static NTSTATUS WvEpAcceptPassive(WDFREQUEST Request, UINT8 *pVerbsData, size_t VerbsSize,\r
+                                                                 WV_ENDPOINT *pEndpoint, WV_IO_EP_ACCEPT *pAttr)\r
+{\r
+       WV_QUEUE_PAIR           *qp;\r
+       iba_cm_rep                      rep;\r
+       NTSTATUS                        status;\r
+\r
+       qp = WvQpAcquire(pEndpoint->pProvider, pAttr->QpId);\r
+       if (qp == NULL) {\r
+               return STATUS_NOT_FOUND;\r
+       }\r
+\r
+       rep.qpn = qp->Qpn;\r
+       rep.starting_psn = (net32_t) RtlRandomEx(&RandomSeed);\r
+       rep.p_pdata = pAttr->Param.Data;\r
+       rep.pdata_len = pAttr->Param.DataLength;\r
+       rep.failover_accepted = IB_FAILOVER_ACCEPT_UNSUPPORTED;\r
+       rep.resp_res = (UINT8) pAttr->Param.ResponderResources;\r
+       rep.init_depth = (UINT8) pAttr->Param.InitiatorDepth;\r
+       rep.flow_ctrl = 1;\r
+       rep.rnr_retry_cnt = pAttr->Param.RnrRetryCount;\r
+       rep.srq = (qp->pSrq != NULL);\r
+\r
+       status = WvEpModifyQpRtr(pEndpoint, qp, pAttr->Param.ResponderResources,\r
+                                                        rep.starting_psn, pVerbsData, VerbsSize);\r
+       if (NT_SUCCESS(status)) {\r
+               status = WvEpModifyQpRts(pEndpoint, qp, pAttr->Param.InitiatorDepth,\r
+                                                                pVerbsData, VerbsSize);\r
+       }\r
+\r
+       WvQpRelease(qp);\r
+\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       WdfObjectAcquireLock(pEndpoint->Queue);\r
+       if (pEndpoint->State != WvEpPassiveConnect) {\r
+               status = STATUS_NOT_SUPPORTED;\r
+               goto release;\r
+       }\r
+\r
+       status = IbCmInterface.CM.send_rep(pEndpoint->pIbCmId, &rep);\r
+       if (NT_SUCCESS(status)) {\r
+               status = WdfRequestForwardToIoQueue(Request, pEndpoint->Queue);\r
+       }\r
+       \r
+       if (!NT_SUCCESS(status)) {\r
+               pEndpoint->State = WvEpDisconnected;\r
+       }\r
+\r
+release:\r
+       WdfObjectReleaseLock(pEndpoint->Queue);\r
+out:\r
+       return status;\r
+}\r
+\r
+void WvEpAccept(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\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
+                                                                                  &pattr, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\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(pProvider, pattr->Id);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       switch (ep->State) {\r
+       case WvEpActiveConnect:\r
+               status = WvEpAcceptActive(Request, out, outlen, ep, pattr);\r
+               break;\r
+       case WvEpPassiveConnect:\r
+               status = WvEpAcceptPassive(Request, out, outlen, ep, pattr);\r
+               break;\r
+       default:\r
+               status = STATUS_NOT_SUPPORTED;\r
+               break;\r
+       }\r
+\r
+       WvEpRelease(ep);\r
+complete:\r
+       if (!NT_SUCCESS(status)) {\r
+               WdfRequestComplete(Request, status);\r
+       }\r
+}\r
+\r
+void WvEpReject(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_ID                        *id;\r
+       WV_ENDPOINT                     *ep;\r
+       NTSTATUS                        status;\r
+       size_t                          len;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_ID), &id, &len);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       ep = WvEpAcquire(pProvider, id->Id);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       WdfObjectAcquireLock(ep->Queue);\r
+       if (ep->State != WvEpActiveConnect && ep->State != WvEpPassiveConnect) {\r
+               status = STATUS_NOT_SUPPORTED;\r
+               goto release;\r
+       }\r
+\r
+       ep->State = WvEpDisconnected;\r
+       status = IbCmInterface.CM.send_rej(ep->pIbCmId, IB_REJ_USER_DEFINED,\r
+                                                                          NULL, 0, id + 1, len - sizeof(WV_IO_ID));\r
+\r
+release:\r
+       WdfObjectReleaseLock(ep->Queue);\r
+       WvEpRelease(ep);\r
+complete:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvEpDisconnect(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UINT64                          *id;\r
+       WV_ENDPOINT                     *ep;\r
+       NTSTATUS                        status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       ep = WvEpAcquire(pProvider, *id);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       WdfObjectAcquireLock(ep->Queue);\r
+       switch (ep->State) {\r
+       case WvEpConnected:\r
+               ep->State = WvEpActiveDisconnect;\r
+               status = IbCmInterface.CM.send_dreq(ep->pIbCmId, NULL, 0);\r
+               break;\r
+       case WvEpPassiveDisconnect:\r
+               ep->State = WvEpDisconnected;\r
+               IbCmInterface.CM.send_drep(ep->pIbCmId, NULL, 0);\r
+               status = STATUS_SUCCESS;\r
+               break;\r
+       default:\r
+               status = STATUS_NOT_SUPPORTED;\r
+               break;\r
+       }\r
+\r
+       WdfObjectReleaseLock(ep->Queue);\r
+       WvEpRelease(ep);\r
+complete:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvEpDisconnectNotify(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UINT64                          *id;\r
+       WV_ENDPOINT                     *ep;\r
+       NTSTATUS                        status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       ep = WvEpAcquire(pProvider, *id);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       WdfObjectAcquireLock(ep->Queue);\r
+       switch (ep->State) {\r
+       case WvEpConnected:\r
+       case WvEpActiveDisconnect:\r
+               status = WdfRequestForwardToIoQueue(Request, ep->Queue);\r
+               break;\r
+       case WvEpPassiveDisconnect:\r
+       case WvEpDisconnected:\r
+               status = STATUS_CONNECTION_DISCONNECTED;\r
+               break;\r
+       default:\r
+               status = STATUS_NOT_SUPPORTED;\r
+               break;\r
+       }\r
+       WdfObjectReleaseLock(ep->Queue);\r
+\r
+       WvEpRelease(ep);\r
+complete:\r
+       if (!NT_SUCCESS(status)) {\r
+               WdfRequestComplete(Request, status);\r
+       }\r
+}\r
+\r
+static NTSTATUS WvEpIbListenHandler(iba_cm_id *pId, iba_cm_event *pEvent)\r
+{\r
+       WV_ENDPOINT             *listen, *ep;\r
+       WDFREQUEST              request;\r
+       NTSTATUS                status;\r
+       IB_CMA_HEADER   *hdr;\r
+\r
+       listen = ((iba_cm_id *) pId->context)->context;\r
+\r
+       WdfObjectAcquireLock(listen->Queue);\r
+       status = WdfIoQueueRetrieveNextRequest(listen->Queue, &request);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto release;\r
+       }\r
+\r
+       ep = CONTAINING_RECORD(RemoveHeadList(&listen->Entry), WV_ENDPOINT, Entry);\r
+       ep->pIbCmId = pId;\r
+       pId->callback = WvEpIbCmHandler;\r
+       pId->context = ep;\r
+\r
+       hdr = pEvent->data.req.req.p_pdata;\r
+       if (hdr->IpVersion == 4) {\r
+               ep->Attributes.LocalAddress.SockAddr.In.SinFamily = WV_AF_INET;\r
+               ep->Attributes.LocalAddress.SockAddr.In.SinAddr = hdr->DstAddress.Ip4.Address;\r
+               ep->Attributes.PeerAddress.SockAddr.In.SinFamily = WV_AF_INET;\r
+               ep->Attributes.PeerAddress.SockAddr.In.SinAddr = hdr->SrcAddress.Ip4.Address;\r
+       } else {\r
+               ep->Attributes.LocalAddress.SockAddr.In6.Sin6Family = WV_AF_INET6; \r
+               RtlCopyMemory(ep->Attributes.LocalAddress.SockAddr.In6.Sin6Addr,\r
+                                         hdr->DstAddress.Ip6Address, 16);\r
+               ep->Attributes.PeerAddress.SockAddr.In6.Sin6Family = WV_AF_INET6;\r
+               RtlCopyMemory(ep->Attributes.PeerAddress.SockAddr.In6.Sin6Addr,\r
+                                         hdr->SrcAddress.Ip6Address, 16);\r
+       }\r
+       ep->Attributes.Device.DeviceGuid = pEvent->data.req.local_ca_guid;\r
+       ep->Attributes.Device.Pkey = pEvent->data.req.req.p_primary_path->pkey;\r
+       ep->Attributes.Device.PortNumber = pEvent->data.req.port_num;\r
+       ep->Attributes.Param.Connect.ResponderResources = pEvent->data.req.req.resp_res;\r
+       ep->Attributes.Param.Connect.InitiatorDepth = pEvent->data.req.req.init_depth;\r
+       ep->Attributes.Param.Connect.RetryCount = pEvent->data.req.req.retry_cnt;\r
+       ep->Attributes.Param.Connect.RnrRetryCount = pEvent->data.req.req.rnr_retry_cnt;\r
+       ep->Attributes.Param.Connect.DataLength = sizeof(ep->Attributes.Param.Connect.Data);\r
+       RtlCopyMemory(ep->Attributes.Param.Connect.Data, hdr + 1,\r
+                                 sizeof(ep->Attributes.Param.Connect.Data));\r
+       ep->Route = *pEvent->data.req.req.p_primary_path;\r
+\r
+       ep->State = WvEpPassiveConnect;\r
+       WvEpPut(ep);\r
+\r
+       WdfRequestComplete(request, STATUS_SUCCESS);\r
+release:\r
+       WdfObjectReleaseLock(listen->Queue);\r
+       return status;\r
+}\r
+\r
+void WvEpListen(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_ENDPOINT                     *ep;\r
+       WV_IO_EP_LISTEN         *pattr;\r
+       NTSTATUS                        status;\r
+       void                            *buf;\r
+       UINT8                           offset, len;\r
+       UINT64                          sid;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_EP_LISTEN),\r
+                                                                                  &pattr, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       ep = WvEpAcquire(pProvider, pattr->Id);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       if (WvAnyAddress(&ep->Attributes.LocalAddress)) {\r
+               buf = NULL;\r
+               offset = 0;\r
+               len = 0;\r
+       } else {\r
+               if (ep->Attributes.LocalAddress.SockAddr.Sa.SaFamily == WV_AF_INET) {\r
+                       buf = &ep->Attributes.LocalAddress.SockAddr.In.SinAddr;\r
+                       len = sizeof ep->Attributes.LocalAddress.SockAddr.In.SinAddr;\r
+                       offset = FIELD_OFFSET(IB_CMA_HEADER, DstAddress.Ip4.Address);\r
+               } else {\r
+                       buf = ep->Attributes.LocalAddress.SockAddr.In6.Sin6Addr;\r
+                       len = sizeof ep->Attributes.LocalAddress.SockAddr.In6.Sin6Addr;\r
+                       offset = FIELD_OFFSET(IB_CMA_HEADER, DstAddress.Ip6Address);\r
+               }\r
+       }\r
+\r
+       WdfObjectAcquireLock(ep->Queue);\r
+       if (ep->State != WvEpAddressBound) {\r
+               status = STATUS_NOT_SUPPORTED;\r
+               goto release;\r
+       }\r
+\r
+       status = IbCmInterface.CM.create_id(WvEpIbListenHandler, ep, &ep->pIbCmId);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto release;\r
+       }\r
+\r
+       ep->Attributes.Param.Backlog = pattr->Backlog;\r
+       ep->State = WvEpListening;\r
+       sid = WvGetServiceId(ep->EpType, &ep->Attributes.LocalAddress);\r
+       status = IbCmInterface.CM.listen(ep->pIbCmId, sid, buf, len, offset);\r
+\r
+release:\r
+       WdfObjectReleaseLock(ep->Queue);\r
+       WvEpRelease(ep);\r
+complete:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvEpGetRequest(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_ENDPOINT                             *listen, *ep;\r
+       WV_IO_EP_GET_REQUEST    *req;\r
+       NTSTATUS                                status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_EP_GET_REQUEST),\r
+                                                                                  &req, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       listen = WvEpAcquire(pProvider, req->Id);\r
+       if (listen == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       if (listen->State != WvEpListening) {\r
+               status = STATUS_NOT_SUPPORTED;\r
+               goto release1;\r
+       }\r
+\r
+       ep = WvEpAcquire(pProvider, req->EpId);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto release1;\r
+       }\r
+\r
+       WdfObjectAcquireLock(ep->Queue);\r
+       if (ep->State == WvEpIdle) {\r
+               ep->State = WvEpQueued;\r
+       } else {\r
+               status = STATUS_CONNECTION_IN_USE;\r
+       }\r
+       WdfObjectReleaseLock(ep->Queue);\r
+\r
+       if (!NT_SUCCESS(status)) {\r
+               goto release2;\r
+       }\r
+\r
+       WdfObjectAcquireLock(listen->Queue);\r
+       status = WdfRequestForwardToIoQueue(Request, listen->Queue);\r
+       if (NT_SUCCESS(status)) {\r
+               InsertTailList(&listen->Entry, &ep->Entry);\r
+               WvEpGet(ep);\r
+       }\r
+       WdfObjectReleaseLock(listen->Queue);\r
+\r
+release2:\r
+       WvEpRelease(ep);\r
+release1:\r
+       WvEpRelease(listen);\r
+complete:\r
+       if (!NT_SUCCESS(status)) {\r
+               WdfRequestComplete(Request, status);\r
+       }\r
+}\r
+\r
+void WvEpLookup(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UNUSED_PARAM(pProvider);\r
+       WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+}\r
+\r
+void WvEpMulticastJoin(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UNUSED_PARAM(pProvider);\r
+       WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+}\r
+\r
+void WvEpMulticastLeave(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UNUSED_PARAM(pProvider);\r
+       WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+}\r
+\r
+//\r
+// Note that the framework may have already canceled outstanding requests.\r
+//\r
+void WvEpCancelListen(WV_ENDPOINT *pListen)\r
+{\r
+       WV_ENDPOINT                     *ep;\r
+       WDFREQUEST                      request;\r
+       NTSTATUS                        status;\r
+\r
+       WdfObjectAcquireLock(pListen->Queue);\r
+       status = WdfIoQueueRetrieveNextRequest(pListen->Queue, &request);\r
+\r
+       while (NT_SUCCESS(status)) {\r
+               WdfRequestComplete(request, STATUS_CANCELLED);\r
+               status = WdfIoQueueRetrieveNextRequest(pListen->Queue, &request);\r
+       }\r
+\r
+       while (!IsListEmpty(&pListen->Entry)) {\r
+               ep = CONTAINING_RECORD(RemoveHeadList(&pListen->Entry), WV_ENDPOINT, Entry);\r
+               ep->State = WvEpIdle;\r
+               WvEpPut(ep);\r
+       }\r
+\r
+       WdfObjectReleaseLock(pListen->Queue);\r
+}\r
+\r
+void WvEpCancel(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UINT64                          *id;\r
+       WV_ENDPOINT                     *ep;\r
+       NTSTATUS                        status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       ep = WvEpAcquire(pProvider, *id);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto out;\r
+       }\r
+\r
+       if (ep->State == WvEpListening) {\r
+               WvEpCancelListen(ep);\r
+       } else {\r
+               WvFlushQueue(ep->Queue, STATUS_CANCELLED);\r
+       }\r
+       WvEpRelease(ep);\r
+\r
+out:\r
+       WdfRequestComplete(Request, status);\r
+}\r