winverbs: transition QP to error on disconnect
authorshefty <shefty@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Wed, 27 May 2009 19:13:36 +0000 (19:13 +0000)
committershefty <shefty@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Wed, 27 May 2009 19:13:36 +0000 (19:13 +0000)
The QP transition into the error state must occur after a DREQ has been
received and acknowledged by the user (by a subsequent call to Disconnect),
or after a DREP has been received.  The current winverbs API requires the
user to call QP:Modify after their NotifyDisconnect completes.  This
presents challenges to implementing an ND provider, which expects a single
function call to perform both operations.

Unlike during connection establishment, the QP transition to error must
sometimes be delayed until after a CM callback.  And since CM callbacks
are at dispatch, we must queue the modify call to a system thread.

Regardless of the outcome of the disconnect attempt or other failures,
the driver tries to transition the QP to error.  This results in some
minor checks to ensure that the correct status is reported to the user.

A couple of additional changes were made to the Accept path to keep the
code consistent, since both Accept and Disconnect have active/passive
code paths.

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

core/winverbs/kernel/wv_driver.c
core/winverbs/kernel/wv_ep.c
core/winverbs/kernel/wv_ep.h
core/winverbs/kernel/wv_provider.c
core/winverbs/kernel/wv_provider.h
core/winverbs/user/wv_ep.cpp
core/winverbs/user/wv_ep.h
core/winverbs/wv_ioctl.h
inc/user/rdma/winverbs.h
ulp/librdmacm/src/cma.cpp

index 434d144..89984c4 100644 (file)
@@ -47,7 +47,6 @@
 #include "wv_ep.h"\r
 \r
 WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WV_RDMA_DEVICE, WvRdmaDeviceGetContext)\r
-WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WV_PROVIDER, WvProviderGetContext)\r
 \r
 WDFDEVICE                              ControlDevice;\r
 static LIST_ENTRY              DevList;\r
@@ -379,11 +378,14 @@ static VOID WvFileCreate(WDFDEVICE Device, WDFREQUEST Request,
                                                 WDFFILEOBJECT FileObject)\r
 {\r
        WV_PROVIDER     *prov = WvProviderGetContext(FileObject);\r
+       NTSTATUS status;\r
 \r
-       WvProviderInit(Device, prov);\r
-       KeAcquireGuardedMutex(&Lock);\r
-       InsertHeadList(&ProvList, &prov->Entry);\r
-       KeReleaseGuardedMutex(&Lock);\r
+       status = WvProviderInit(Device, prov);\r
+       if (NT_SUCCESS(status)) {\r
+               KeAcquireGuardedMutex(&Lock);\r
+               InsertHeadList(&ProvList, &prov->Entry);\r
+               KeReleaseGuardedMutex(&Lock);\r
+       }\r
        WdfRequestComplete(Request, STATUS_SUCCESS);\r
 }\r
 \r
index ee89253..964cc3b 100644 (file)
@@ -369,6 +369,112 @@ static void WvEpSaveReject(WV_ENDPOINT *pEndpoint, iba_cm_rej_event *pReject)
        pEndpoint->Attributes.Param.Connect.DataLength = len;\r
 }\r
 \r
+static NTSTATUS WvEpModifyQpErr(WV_QUEUE_PAIR *pQp,\r
+                                                               UINT8 *pVerbsData, UINT32 VerbsSize)\r
+{\r
+       ib_qp_mod_t                     attr;\r
+       ib_api_status_t         ib_status;\r
+       NTSTATUS                        status;\r
+\r
+       attr.req_state = IB_QPS_ERROR;\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 WvEpDisconnectQp(WV_PROVIDER *pProvider, UINT64 QpId,\r
+                                                                UINT8 *pVerbsData, UINT32 VerbsSize)\r
+{\r
+       WV_QUEUE_PAIR   *qp;\r
+       NTSTATUS                status;\r
+\r
+       if (QpId == 0) {\r
+               return STATUS_SUCCESS;\r
+       }\r
+\r
+       qp = WvQpAcquire(pProvider, QpId);\r
+       if (qp == NULL) {\r
+               return STATUS_NOT_FOUND;\r
+       }\r
+\r
+       status = WvEpModifyQpErr(qp, pVerbsData, VerbsSize);\r
+       WvQpRelease(qp);\r
+\r
+       return status;\r
+}\r
+\r
+static void WvEpDisconnectHandler(WORK_ENTRY *pWork)\r
+{\r
+       WORK_ENTRY                      *work;\r
+       WV_PROVIDER                     *prov;\r
+       WDFREQUEST                      request;\r
+       WV_IO_EP_DISCONNECT     *pattr;\r
+       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
+                                                                                  &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
+       status = (NTSTATUS) WdfRequestGetInformation(request);\r
+       if (NT_SUCCESS(status)) {\r
+               status = WvEpDisconnectQp(prov, pattr->QpId, out, outlen);\r
+       } else {\r
+               WvEpDisconnectQp(prov, pattr->QpId, out, outlen);\r
+       }\r
+\r
+complete:\r
+       WdfRequestCompleteWithInformation(request, status, outlen);\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
+       WDF_REQUEST_PARAMETERS  param;\r
+       WORK_ENTRY                              *work;\r
+       NTSTATUS                                status;\r
+\r
+       WdfObjectAcquireLock(pEndpoint->Queue);\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
+                       WorkQueueInsert(&pEndpoint->pProvider->WorkQueue, work);\r
+               } else {\r
+                       WdfRequestComplete(request, DiscStatus);\r
+               }\r
+\r
+               WdfObjectAcquireLock(pEndpoint->Queue);\r
+               status = WdfIoQueueRetrieveNextRequest(pEndpoint->Queue, &request);\r
+       }\r
+       WdfObjectReleaseLock(pEndpoint->Queue);\r
+}\r
+\r
 static NTSTATUS WvEpIbCmHandler(iba_cm_id *pId, iba_cm_event *pEvent)\r
 {\r
        WV_ENDPOINT     *ep;\r
@@ -377,12 +483,14 @@ static NTSTATUS WvEpIbCmHandler(iba_cm_id *pId, iba_cm_event *pEvent)
        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_dreq_error:\r
+               WvEpCompleteDisconnect(ep, STATUS_IO_TIMEOUT);\r
+               break;\r
        case iba_cm_rep_received:\r
                WdfObjectAcquireLock(ep->Queue);\r
                if (ep->State == WvEpActiveConnect) {\r
@@ -394,8 +502,8 @@ static NTSTATUS WvEpIbCmHandler(iba_cm_id *pId, iba_cm_event *pEvent)
        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
+                       WvCompleteRequestsWithInformation(ep->Queue, STATUS_SUCCESS);\r
                }\r
                WdfObjectReleaseLock(ep->Queue);\r
                break;\r
@@ -403,18 +511,15 @@ static NTSTATUS WvEpIbCmHandler(iba_cm_id *pId, iba_cm_event *pEvent)
                WdfObjectAcquireLock(ep->Queue);\r
                if (ep->State == WvEpConnected) {\r
                        ep->State = WvEpPassiveDisconnect;\r
+                       WvCompleteRequests(ep->Queue, STATUS_SUCCESS);\r
+                       WdfObjectReleaseLock(ep->Queue);\r
                } else {\r
-                       ep->State = WvEpDisconnected;\r
-                       IbCmInterface.CM.send_drep(pId, NULL, 0);\r
+                       WdfObjectReleaseLock(ep->Queue);\r
+                       WvEpCompleteDisconnect(ep, STATUS_SUCCESS);\r
                }\r
-               WvCompleteRequests(ep->Queue, STATUS_SUCCESS);\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_SUCCESS);\r
-               WdfObjectReleaseLock(ep->Queue);\r
+               WvEpCompleteDisconnect(ep, STATUS_SUCCESS);\r
                break;\r
        case iba_cm_rej_received:\r
                WdfObjectAcquireLock(ep->Queue);\r
@@ -619,7 +724,9 @@ static NTSTATUS WvEpAcceptActive(WDFREQUEST Request, UINT8 *pVerbsData, size_t V
        pEndpoint->State = WvEpConnected;\r
        status = IbCmInterface.CM.send_rtu(pEndpoint->pIbCmId, pAttr->Param.Data,\r
                                                                           pAttr->Param.DataLength);\r
-       if (!NT_SUCCESS(status)) {\r
+       if (NT_SUCCESS(status)) {\r
+               WdfRequestCompleteWithInformation(Request, status, VerbsSize);\r
+       } else {\r
                pEndpoint->State = WvEpDisconnected;\r
        }\r
 \r
@@ -715,16 +822,13 @@ void WvEpAccept(WV_PROVIDER *pProvider, WDFREQUEST Request)
                goto complete;\r
        }\r
 \r
+       /* EP state is re-checked under lock in WvEpAccept* calls */\r
        switch (ep->State) {\r
        case WvEpActiveConnect:\r
                status = WvEpAcceptActive(Request, out, outlen, ep, pattr);\r
                break;\r
        case WvEpPassiveConnect:\r
                status = WvEpAcceptPassive(Request, out, outlen, ep, pattr);\r
-               if (NT_SUCCESS(status)) {\r
-                       WvEpRelease(ep);\r
-                       return;\r
-               }\r
                break;\r
        default:\r
                status = STATUS_NOT_SUPPORTED;\r
@@ -733,7 +837,9 @@ void WvEpAccept(WV_PROVIDER *pProvider, WDFREQUEST Request)
 \r
        WvEpRelease(ep);\r
 complete:\r
-       WdfRequestComplete(Request, status);\r
+       if (!NT_SUCCESS(status)) {\r
+               WdfRequestComplete(Request, status);\r
+       }\r
 }\r
 \r
 void WvEpReject(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
@@ -771,43 +877,112 @@ 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
 void WvEpDisconnect(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
 {\r
-       UINT64                          *id;\r
+       WV_IO_EP_DISCONNECT     *pattr;\r
        WV_ENDPOINT                     *ep;\r
        NTSTATUS                        status;\r
+       UINT8                           *out;\r
+       size_t                          outlen;\r
 \r
-       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_EP_DISCONNECT),\r
+                                                                                  &pattr, NULL);\r
        if (!NT_SUCCESS(status)) {\r
                goto complete;\r
        }\r
 \r
-       ep = WvEpAcquire(pProvider, *id);\r
+       status = WdfRequestRetrieveOutputBuffer(Request, 0, &out, &outlen);\r
+       if (!NT_SUCCESS(status) && status != STATUS_BUFFER_TOO_SMALL) {\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
+       /* EP state is re-checked under lock in WvEpDisconnect* calls */\r
        switch (ep->State) {\r
        case WvEpConnected:\r
-               ep->State = WvEpActiveDisconnect;\r
-               status = IbCmInterface.CM.send_dreq(ep->pIbCmId, NULL, 0);\r
+               status = WvEpDisconnectActive(Request, out, outlen, ep, pattr);\r
                break;\r
        case WvEpPassiveDisconnect:\r
-               ep->State = WvEpDisconnected;\r
-               IbCmInterface.CM.send_drep(ep->pIbCmId, NULL, 0);\r
-               status = STATUS_SUCCESS;\r
+               status = WvEpDisconnectPassive(Request, out, outlen, ep, pattr);\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
+       if (!NT_SUCCESS(status)) {\r
+               WdfRequestComplete(Request, status);\r
+       }\r
 }\r
 \r
 void WvEpDisconnectNotify(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
@@ -1052,23 +1227,15 @@ void WvEpMulticastLeave(WV_PROVIDER *pProvider, WDFREQUEST Request)
 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
+       WvCompleteRequests(pListen->Queue, STATUS_CANCELLED);\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
index 703a964..10d0d7d 100644 (file)
@@ -35,6 +35,7 @@
 #include <ntddk.h>\r
 #include <wdm.h>\r
 \r
+#include "work_queue.h"\r
 #include <iba\ib_types.h>\r
 #include <iba\ib_ci.h>\r
 #include "wv_provider.h"\r
index dbf2286..19053a8 100644 (file)
@@ -29,6 +29,7 @@
 \r
 #include <ntstatus.h>\r
 \r
+#include "work_queue.c"\r
 #include <rdma\wvstatus.h>\r
 #include "wv_driver.h"\r
 #include "wv_ioctl.h"\r
@@ -52,8 +53,15 @@ void WvProviderPut(WV_PROVIDER *pProvider)
        }\r
 }\r
 \r
-void WvProviderInit(WDFDEVICE Device, WV_PROVIDER *pProvider)\r
+NTSTATUS WvProviderInit(WDFDEVICE Device, WV_PROVIDER *pProvider)\r
 {\r
+       NTSTATUS status;\r
+\r
+       status = WorkQueueInit(&pProvider->WorkQueue, WdfDeviceWdmGetDeviceObject(Device), 0);\r
+       if (!NT_SUCCESS(status)) {\r
+               return status;\r
+       }\r
+\r
        IndexListInit(&pProvider->DevIndex);\r
        IndexListInit(&pProvider->CqIndex);\r
        IndexListInit(&pProvider->PdIndex);\r
@@ -72,6 +80,7 @@ void WvProviderInit(WDFDEVICE Device, WV_PROVIDER *pProvider)
        KeInitializeEvent(&pProvider->SharedEvent, NotificationEvent, FALSE);\r
        pProvider->Exclusive = 0;\r
        KeInitializeEvent(&pProvider->ExclusiveEvent, SynchronizationEvent, FALSE);\r
+       return STATUS_SUCCESS;\r
 }\r
 \r
 void WvProviderCleanup(WV_PROVIDER *pProvider)\r
@@ -136,6 +145,7 @@ void WvProviderCleanup(WV_PROVIDER *pProvider)
        IndexListDestroy(&pProvider->PdIndex);\r
        IndexListDestroy(&pProvider->CqIndex);\r
        IndexListDestroy(&pProvider->DevIndex);\r
+       WorkQueueDestroy(&pProvider->WorkQueue);\r
 }\r
 \r
 // See comment above WvProviderRemoveHandler.\r
index 2054551..329145f 100644 (file)
@@ -36,6 +36,7 @@
 #include <wdf.h>\r
 #include <wdm.h>\r
 \r
+#include "work_queue.h"\r
 #include <complib\cl_qmap.h>\r
 #include "wv_driver.h"\r
 #include "index_list.h"\r
@@ -64,11 +65,15 @@ typedef struct _WV_PROVIDER
        LONG                    Exclusive;\r
        KEVENT                  ExclusiveEvent;\r
 \r
+       WORK_QUEUE              WorkQueue;\r
+\r
 }      WV_PROVIDER;\r
 \r
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WV_PROVIDER, WvProviderGetContext)\r
+\r
 void WvProviderGet(WV_PROVIDER *pProvider);\r
 void WvProviderPut(WV_PROVIDER *pProvider);\r
-void WvProviderInit(WDFDEVICE Device, WV_PROVIDER *pProvider);\r
+NTSTATUS WvProviderInit(WDFDEVICE Device, WV_PROVIDER *pProvider);\r
 void WvProviderCleanup(WV_PROVIDER *pProvider);\r
 \r
 void WvProviderRemoveHandler(WV_PROVIDER *pProvider, WV_RDMA_DEVICE *pDevice);\r
index 60ea068..e9a96b3 100644 (file)
@@ -339,13 +339,27 @@ Accept(IWVConnectQueuePair* pQp, WV_CONNECT_PARAM* pParam, OVERLAPPED* pOverlapp
 }\r
 \r
 STDMETHODIMP CWVConnectEndpoint::\r
-Disconnect(void)\r
+Disconnect(IWVConnectQueuePair* pQp, OVERLAPPED* pOverlapped)\r
 {\r
-       DWORD           bytes;\r
-       HRESULT         hr;\r
+       CWVConnectQueuePair     *qp = (CWVConnectQueuePair *) pQp;\r
+       WV_IO_EP_DISCONNECT     attr;\r
+       DWORD                           bytes;\r
+       HRESULT                         hr;\r
+       void                            *pout;\r
+       DWORD                           size;\r
+\r
+       attr.Id = m_Id;\r
+       if (pQp != NULL) {\r
+               attr.QpId = qp->m_Id;\r
+               qp->m_pVerbs->nd_modify_qp(qp->m_hVerbsQp, &pout, &size);\r
+       } else {\r
+               attr.QpId = 0;\r
+               pout = NULL;\r
+               size = 0;\r
+       }\r
 \r
        if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_DISCONNECT,\r
-                                                 &m_Id, sizeof m_Id, NULL, 0, &bytes, NULL)) {\r
+                                                 &attr, sizeof attr, pout, size, &bytes, pOverlapped)) {\r
                hr = WV_SUCCESS;\r
        } else {\r
                hr = HRESULT_FROM_WIN32(GetLastError());\r
index 1d3ee5f..fbbe7be 100644 (file)
@@ -61,7 +61,7 @@ public:
                                                 WV_CONNECT_PARAM* pParam, OVERLAPPED* pOverlapped);\r
        STDMETHODIMP Accept(IWVConnectQueuePair* pQp, WV_CONNECT_PARAM* pParam,\r
                                                OVERLAPPED* pOverlapped);\r
-       STDMETHODIMP Disconnect();\r
+       STDMETHODIMP Disconnect(IWVConnectQueuePair* pQp, OVERLAPPED* pOverlapped);\r
        STDMETHODIMP NotifyDisconnect(OVERLAPPED* pOverlapped);\r
        STDMETHODIMP Query(WV_CONNECT_ATTRIBUTES* pAttributes);\r
 \r
index 0470bc2..7499d4b 100644 (file)
@@ -272,7 +272,7 @@ enum {
 #define WV_IOCTL_EP_ACCEPT                             WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
                                                                                                 WV_IO_FUNCTION_EP_ACCEPT)\r
 \r
-// UINT64 Id / none\r
+// WV_IO_EP_DISCONNECT/ verbs specific\r
 #define WV_IOCTL_EP_DISCONNECT                 WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
                                                                                                 WV_IO_FUNCTION_EP_DISCONNECT)\r
 \r
@@ -737,4 +737,11 @@ typedef struct _WV_IO_EP_ATTRIBUTES
 \r
 }      WV_IO_EP_ATTRIBUTES;\r
 \r
+typedef struct _WV_IO_EP_DISCONNECT\r
+{\r
+       UINT64                                  Id;\r
+       UINT64                                  QpId;\r
+\r
+}      WV_IO_EP_DISCONNECT;\r
+\r
 #endif // _WV_IOCTL_H_\r
index 9c0732e..af2d8b2 100644 (file)
@@ -1156,9 +1156,9 @@ DECLARE_INTERFACE_(IWVEndpoint, IWVOverlapped)
 \r
 #undef INTERFACE\r
 #define INTERFACE IWVConnectEndpoint\r
-// {ac670274-1934-4759-a39c-eee01a8130b3}\r
-DEFINE_GUID(IID_IWVConnectEndpoint, 0xac670274, 0x1934, 0x4759,\r
-                       0xa3, 0x9c, 0xee, 0xe0, 0x1a, 0x81, 0x30, 0xb3);\r
+// {B7C6708E-EA9C-4cff-B2CF-35BCA9A3739A}\r
+DEFINE_GUID(IID_IWVConnectEndpoint, 0xb7c6708e, 0xea9c, 0x4cff,\r
+                       0xb2, 0xcf, 0x35, 0xbc, 0xa9, 0xa3, 0x73, 0x9a);\r
 \r
 DECLARE_INTERFACE_(IWVConnectEndpoint, IWVEndpoint)\r
 {\r
@@ -1236,7 +1236,9 @@ DECLARE_INTERFACE_(IWVConnectEndpoint, IWVEndpoint)
                ) PURE;\r
 \r
        STDMETHOD(Disconnect)(\r
-               THIS\r
+               THIS_\r
+               __in_opt IWVConnectQueuePair* pQp,\r
+               __in_opt OVERLAPPED* pOverlapped\r
                ) PURE;\r
 \r
        STDMETHOD(NotifyDisconnect)(\r
index d1f7168..9fb0b25 100644 (file)
@@ -811,7 +811,7 @@ int rdma_disconnect(struct rdma_cm_id *id)
        } else {\r
                id_priv->state = cma_disconnected;\r
        }\r
-       hr = id->ep.connect->Disconnect();\r
+       hr = id->ep.connect->Disconnect(id->qp->conn_handle, NULL);\r
        if (FAILED(hr)) {\r
                return hr;\r
        }\r