[ofw] [RFC] [PATCH 2/2 v3] winverbs: transition QP to error on disconnect

Sean Hefty sean.hefty at intel.com
Tue May 26 16:17:32 PDT 2009


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 at intel.com>
---
changes from v2:
Reverted back to using the work queue abstraction to handle a small pool
of work items.

Uses the IRP DriverContext field as the work entry.  This avoids a
memory allocation during the disconnect.  However, it does violate a
documentation note that framework drivers should not use the
driver context.  In this case, I believe that the use of the driver
context is safe.  (Testing hasn't shown any problems as of yet.)  If
this is shown not to be the case, the fix is simple, but involves
allocating a new structure during disconnect.

diff -up -r -X \mshefty\scm\winof\trunk\docs\dontdiff.txt -I '\$Id:' trunk\core\winverbs/kernel/wv_driver.c
branches\winverbs\core\winverbs/kernel/wv_driver.c
--- trunk\core\winverbs/kernel/wv_driver.c	2009-04-28 14:53:06.404875000 -0700
+++ branches\winverbs\core\winverbs/kernel/wv_driver.c	2009-05-26 11:40:17.694098200 -0700
@@ -47,7 +47,6 @@
 #include "wv_ep.h"
 
 WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WV_RDMA_DEVICE, WvRdmaDeviceGetContext)
-WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WV_PROVIDER, WvProviderGetContext)
 
 WDFDEVICE				ControlDevice;
 static LIST_ENTRY		DevList;
@@ -379,11 +378,14 @@ static VOID WvFileCreate(WDFDEVICE Devic
 						 WDFFILEOBJECT FileObject)
 {
 	WV_PROVIDER	*prov = WvProviderGetContext(FileObject);
+	NTSTATUS status;
 
-	WvProviderInit(Device, prov);
-	KeAcquireGuardedMutex(&Lock);
-	InsertHeadList(&ProvList, &prov->Entry);
-	KeReleaseGuardedMutex(&Lock);
+	status = WvProviderInit(Device, prov);
+	if (NT_SUCCESS(status)) {
+		KeAcquireGuardedMutex(&Lock);
+		InsertHeadList(&ProvList, &prov->Entry);
+		KeReleaseGuardedMutex(&Lock);
+	}
 	WdfRequestComplete(Request, STATUS_SUCCESS);
 }
 
diff -up -r -X \mshefty\scm\winof\trunk\docs\dontdiff.txt -I '\$Id:' trunk\core\winverbs/kernel/wv_ep.c
branches\winverbs\core\winverbs/kernel/wv_ep.c
--- trunk\core\winverbs/kernel/wv_ep.c	2009-04-01 15:51:01.289540300 -0700
+++ branches\winverbs\core\winverbs/kernel/wv_ep.c	2009-05-26 14:58:40.492800300 -0700
@@ -369,6 +369,112 @@ static void WvEpSaveReject(WV_ENDPOINT *
 	pEndpoint->Attributes.Param.Connect.DataLength = len;
 }
 
+static NTSTATUS WvEpModifyQpErr(WV_QUEUE_PAIR *pQp,
+								UINT8 *pVerbsData, UINT32 VerbsSize)
+{
+	ib_qp_mod_t			attr;
+	ib_api_status_t		ib_status;
+	NTSTATUS			status;
+
+	attr.req_state = IB_QPS_ERROR;
+	ib_status = pQp->pVerbs->ndi_modify_qp(pQp->hVerbsQp, &attr, NULL,
+										   VerbsSize, pVerbsData);
+	if (ib_status != IB_SUCCESS) {
+		return STATUS_UNSUCCESSFUL;
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static NTSTATUS WvEpDisconnectQp(WV_PROVIDER *pProvider, UINT64 QpId,
+								 UINT8 *pVerbsData, UINT32 VerbsSize)
+{
+	WV_QUEUE_PAIR	*qp;
+	NTSTATUS		status;
+
+	if (QpId == 0) {
+		return STATUS_SUCCESS;
+	}
+
+	qp = WvQpAcquire(pProvider, QpId);
+	if (qp == NULL) {
+		return STATUS_NOT_FOUND;
+	}
+
+	status = WvEpModifyQpErr(qp, pVerbsData, VerbsSize);
+	WvQpRelease(qp);
+
+	return status;
+}
+
+static void WvEpDisconnectHandler(WORK_ENTRY *pWork)
+{
+	WORK_ENTRY			*work;
+	WV_PROVIDER			*prov;
+	WDFREQUEST			request;
+	WV_IO_EP_DISCONNECT	*pattr;
+	UINT8				*out;
+	size_t				outlen = 0;
+	NTSTATUS			status;
+
+	request = (WDFREQUEST) pWork->Context;
+	prov = WvProviderGetContext(WdfRequestGetFileObject(request));
+
+	status = WdfRequestRetrieveInputBuffer(request, sizeof(WV_IO_EP_DISCONNECT),
+										   &pattr, NULL);
+	if (!NT_SUCCESS(status)) {
+		goto complete;
+	}
+
+	status = WdfRequestRetrieveOutputBuffer(request, 0, &out, &outlen);
+	if (!NT_SUCCESS(status) && status != STATUS_BUFFER_TOO_SMALL) {
+		goto complete;
+	}
+
+	status = (NTSTATUS) WdfRequestGetInformation(request);
+	if (NT_SUCCESS(status)) {
+		status = WvEpDisconnectQp(prov, pattr->QpId, out, outlen);
+	} else {
+		WvEpDisconnectQp(prov, pattr->QpId, out, outlen);
+	}
+
+complete:
+	WdfRequestCompleteWithInformation(request, status, outlen);
+}
+
+// We use IRP DriverContext to queue the request for further processing,
+// but the request/IRP are no longer owned by the framework.
+static void WvEpCompleteDisconnect(WV_ENDPOINT *pEndpoint, NTSTATUS DiscStatus)
+{
+	WDFREQUEST				request;
+	WDF_REQUEST_PARAMETERS	param;
+	WORK_ENTRY				*work;
+	NTSTATUS				status;
+
+	WdfObjectAcquireLock(pEndpoint->Queue);
+	pEndpoint->State = WvEpDisconnected;
+
+	status = WdfIoQueueRetrieveNextRequest(pEndpoint->Queue, &request);
+	while (NT_SUCCESS(status)) {
+		WdfObjectReleaseLock(pEndpoint->Queue);
+
+		WDF_REQUEST_PARAMETERS_INIT(&param);
+		WdfRequestGetParameters(request, &param);
+		if (param.Parameters.DeviceIoControl.IoControlCode == WV_IOCTL_EP_DISCONNECT) {
+			work = WorkEntryFromIrp(WdfRequestWdmGetIrp(request));
+			WdfRequestSetInformation(request, DiscStatus);
+			WorkEntryInit(work, WvEpDisconnectHandler, request);
+			WorkQueueInsert(&pEndpoint->pProvider->WorkQueue, work);
+		} else {
+			WdfRequestComplete(request, DiscStatus);
+		}
+
+		WdfObjectAcquireLock(pEndpoint->Queue);
+		status = WdfIoQueueRetrieveNextRequest(pEndpoint->Queue, &request);
+	}
+	WdfObjectReleaseLock(pEndpoint->Queue);
+}
+
 static NTSTATUS WvEpIbCmHandler(iba_cm_id *pId, iba_cm_event *pEvent)
 {
 	WV_ENDPOINT	*ep;
@@ -377,12 +483,14 @@ static NTSTATUS WvEpIbCmHandler(iba_cm_i
 	switch (pEvent->type) {
 	case iba_cm_req_error:
 	case iba_cm_rep_error:
-	case iba_cm_dreq_error:
 		WdfObjectAcquireLock(ep->Queue);
 		ep->State = WvEpDisconnected;
 		WvCompleteRequests(ep->Queue, STATUS_IO_TIMEOUT);
 		WdfObjectReleaseLock(ep->Queue);
 		break;
+	case iba_cm_dreq_error:
+		WvEpCompleteDisconnect(ep, STATUS_IO_TIMEOUT);
+		break;
 	case iba_cm_rep_received:
 		WdfObjectAcquireLock(ep->Queue);
 		if (ep->State == WvEpActiveConnect) {
@@ -394,8 +502,8 @@ static NTSTATUS WvEpIbCmHandler(iba_cm_i
 	case iba_cm_rtu_received:
 		WdfObjectAcquireLock(ep->Queue);
 		if (ep->State == WvEpPassiveConnect) {
-			WvCompleteRequestsWithInformation(ep->Queue, STATUS_SUCCESS);
 			ep->State = WvEpConnected;
+			WvCompleteRequestsWithInformation(ep->Queue, STATUS_SUCCESS);
 		}
 		WdfObjectReleaseLock(ep->Queue);
 		break;
@@ -403,18 +511,15 @@ static NTSTATUS WvEpIbCmHandler(iba_cm_i
 		WdfObjectAcquireLock(ep->Queue);
 		if (ep->State == WvEpConnected) {
 			ep->State = WvEpPassiveDisconnect;
+			WvCompleteRequests(ep->Queue, STATUS_SUCCESS);
+			WdfObjectReleaseLock(ep->Queue);
 		} else {
-			ep->State = WvEpDisconnected;
-			IbCmInterface.CM.send_drep(pId, NULL, 0);
+			WdfObjectReleaseLock(ep->Queue);
+			WvEpCompleteDisconnect(ep, STATUS_SUCCESS);
 		}
-		WvCompleteRequests(ep->Queue, STATUS_SUCCESS);
-		WdfObjectReleaseLock(ep->Queue);
 		break;
 	case iba_cm_drep_received:
-		WdfObjectAcquireLock(ep->Queue);
-		ep->State = WvEpDisconnected;
-		WvCompleteRequests(ep->Queue, STATUS_SUCCESS);
-		WdfObjectReleaseLock(ep->Queue);
+		WvEpCompleteDisconnect(ep, STATUS_SUCCESS);
 		break;
 	case iba_cm_rej_received:
 		WdfObjectAcquireLock(ep->Queue);
@@ -619,7 +724,9 @@ static NTSTATUS WvEpAcceptActive(WDFREQU
 	pEndpoint->State = WvEpConnected;
 	status = IbCmInterface.CM.send_rtu(pEndpoint->pIbCmId, pAttr->Param.Data,
 									   pAttr->Param.DataLength);
-	if (!NT_SUCCESS(status)) {
+	if (NT_SUCCESS(status)) {
+		WdfRequestCompleteWithInformation(Request, status, VerbsSize);
+	} else {
 		pEndpoint->State = WvEpDisconnected;
 	}
 
@@ -715,16 +822,13 @@ void WvEpAccept(WV_PROVIDER *pProvider, 
 		goto complete;
 	}
 
+	/* EP state is re-checked under lock in WvEpAccept* calls */
 	switch (ep->State) {
 	case WvEpActiveConnect:
 		status = WvEpAcceptActive(Request, out, outlen, ep, pattr);
 		break;
 	case WvEpPassiveConnect:
 		status = WvEpAcceptPassive(Request, out, outlen, ep, pattr);
-		if (NT_SUCCESS(status)) {
-			WvEpRelease(ep);
-			return;
-		}
 		break;
 	default:
 		status = STATUS_NOT_SUPPORTED;
@@ -733,7 +837,9 @@ void WvEpAccept(WV_PROVIDER *pProvider, 
 
 	WvEpRelease(ep);
 complete:
-	WdfRequestComplete(Request, status);
+	if (!NT_SUCCESS(status)) {
+		WdfRequestComplete(Request, status);
+	}
 }
 
 void WvEpReject(WV_PROVIDER *pProvider, WDFREQUEST Request)
@@ -771,43 +877,112 @@ complete:
 	WdfRequestComplete(Request, status);
 }
 
+static NTSTATUS WvEpDisconnectActive(WDFREQUEST Request,
+									 UINT8 *pVerbsData, size_t VerbsSize,
+									 WV_ENDPOINT *pEndpoint,
+									 WV_IO_EP_DISCONNECT *pAttr)
+{
+	NTSTATUS status, failure;
+
+	WdfObjectAcquireLock(pEndpoint->Queue);
+	if (pEndpoint->State != WvEpConnected) {
+		status = STATUS_NOT_SUPPORTED;
+		goto release;
+	}
+
+	pEndpoint->State = WvEpActiveDisconnect;
+	IbCmInterface.CM.send_dreq(pEndpoint->pIbCmId, NULL, 0);
+
+	status = WdfRequestForwardToIoQueue(Request, pEndpoint->Queue);
+	if (!NT_SUCCESS(status)) {
+		pEndpoint->State = WvEpDisconnected;
+		WvCompleteRequests(pEndpoint->Queue, STATUS_UNSUCCESSFUL);
+		WdfObjectReleaseLock(pEndpoint->Queue);
+
+		failure = status;
+		status = WvEpDisconnectQp(pEndpoint->pProvider, pAttr->QpId,
+								  pVerbsData, VerbsSize);
+		if (NT_SUCCESS(status)) {
+			WdfRequestCompleteWithInformation(Request, failure, VerbsSize);
+		}
+		return status;
+	}
+
+release:
+	WdfObjectReleaseLock(pEndpoint->Queue);
+	return status;
+}
+
+static NTSTATUS WvEpDisconnectPassive(WDFREQUEST Request,
+									  UINT8 *pVerbsData, size_t VerbsSize,
+									  WV_ENDPOINT *pEndpoint,
+									  WV_IO_EP_DISCONNECT *pAttr)
+{
+	NTSTATUS status;
+
+	WdfObjectAcquireLock(pEndpoint->Queue);
+	if (pEndpoint->State != WvEpPassiveDisconnect) {
+		WdfObjectReleaseLock(pEndpoint->Queue);
+		return STATUS_NOT_SUPPORTED;
+	}
+
+	pEndpoint->State = WvEpDisconnected;
+	WdfObjectReleaseLock(pEndpoint->Queue);
+
+	IbCmInterface.CM.send_drep(pEndpoint->pIbCmId, NULL, 0);
+
+	status = WvEpDisconnectQp(pEndpoint->pProvider, pAttr->QpId,
+							  pVerbsData, VerbsSize);
+	if (NT_SUCCESS(status)) {
+		WdfRequestCompleteWithInformation(Request, status, VerbsSize);
+	}
+
+	return status;
+}
+
 void WvEpDisconnect(WV_PROVIDER *pProvider, WDFREQUEST Request)
 {
-	UINT64				*id;
+	WV_IO_EP_DISCONNECT	*pattr;
 	WV_ENDPOINT			*ep;
 	NTSTATUS			status;
+	UINT8				*out;
+	size_t				outlen;
 
-	status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);
+	status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_EP_DISCONNECT),
+										   &pattr, NULL);
 	if (!NT_SUCCESS(status)) {
 		goto complete;
 	}
 
-	ep = WvEpAcquire(pProvider, *id);
+	status = WdfRequestRetrieveOutputBuffer(Request, 0, &out, &outlen);
+	if (!NT_SUCCESS(status) && status != STATUS_BUFFER_TOO_SMALL) {
+		goto complete;
+	}
+
+	ep = WvEpAcquire(pProvider, pattr->Id);
 	if (ep == NULL) {
 		status = STATUS_NOT_FOUND;
 		goto complete;
 	}
 
-	WdfObjectAcquireLock(ep->Queue);
+	/* EP state is re-checked under lock in WvEpDisconnect* calls */
 	switch (ep->State) {
 	case WvEpConnected:
-		ep->State = WvEpActiveDisconnect;
-		status = IbCmInterface.CM.send_dreq(ep->pIbCmId, NULL, 0);
+		status = WvEpDisconnectActive(Request, out, outlen, ep, pattr);
 		break;
 	case WvEpPassiveDisconnect:
-		ep->State = WvEpDisconnected;
-		IbCmInterface.CM.send_drep(ep->pIbCmId, NULL, 0);
-		status = STATUS_SUCCESS;
+		status = WvEpDisconnectPassive(Request, out, outlen, ep, pattr);
 		break;
 	default:
 		status = STATUS_NOT_SUPPORTED;
 		break;
 	}
 
-	WdfObjectReleaseLock(ep->Queue);
 	WvEpRelease(ep);
 complete:
-	WdfRequestComplete(Request, status);
+	if (!NT_SUCCESS(status)) {
+		WdfRequestComplete(Request, status);
+	}
 }
 
 void WvEpDisconnectNotify(WV_PROVIDER *pProvider, WDFREQUEST Request)
@@ -1052,23 +1227,15 @@ void WvEpMulticastLeave(WV_PROVIDER *pPr
 void WvEpCancelListen(WV_ENDPOINT *pListen)
 {
 	WV_ENDPOINT			*ep;
-	WDFREQUEST			request;
-	NTSTATUS			status;
 
 	WdfObjectAcquireLock(pListen->Queue);
-	status = WdfIoQueueRetrieveNextRequest(pListen->Queue, &request);
-
-	while (NT_SUCCESS(status)) {
-		WdfRequestComplete(request, STATUS_CANCELLED);
-		status = WdfIoQueueRetrieveNextRequest(pListen->Queue, &request);
-	}
+	WvCompleteRequests(pListen->Queue, STATUS_CANCELLED);
 
 	while (!IsListEmpty(&pListen->Entry)) {
 		ep = CONTAINING_RECORD(RemoveHeadList(&pListen->Entry), WV_ENDPOINT, Entry);
 		ep->State = WvEpIdle;
 		WvEpPut(ep);
 	}
-
 	WdfObjectReleaseLock(pListen->Queue);
 }
 
diff -up -r -X \mshefty\scm\winof\trunk\docs\dontdiff.txt -I '\$Id:' trunk\core\winverbs/kernel/wv_ep.h
branches\winverbs\core\winverbs/kernel/wv_ep.h
--- trunk\core\winverbs/kernel/wv_ep.h	2009-01-24 11:41:22.265625000 -0800
+++ branches\winverbs\core\winverbs/kernel/wv_ep.h	2009-05-26 11:55:43.566399700 -0700
@@ -35,6 +35,7 @@
 #include <ntddk.h>
 #include <wdm.h>
 
+#include "work_queue.h"
 #include <iba\ib_types.h>
 #include <iba\ib_ci.h>
 #include "wv_provider.h"
diff -up -r -X \mshefty\scm\winof\trunk\docs\dontdiff.txt -I '\$Id:' trunk\core\winverbs/kernel/wv_provider.c
branches\winverbs\core\winverbs/kernel/wv_provider.c
--- trunk\core\winverbs/kernel/wv_provider.c	2009-01-05 17:54:44.895851600 -0800
+++ branches\winverbs\core\winverbs/kernel/wv_provider.c	2009-05-26 12:06:42.267273000 -0700
@@ -29,6 +29,7 @@
 
 #include <ntstatus.h>
 
+#include "work_queue.c"
 #include <rdma\wvstatus.h>
 #include "wv_driver.h"
 #include "wv_ioctl.h"
@@ -52,8 +53,15 @@ void WvProviderPut(WV_PROVIDER *pProvide
 	}
 }
 
-void WvProviderInit(WDFDEVICE Device, WV_PROVIDER *pProvider)
+NTSTATUS WvProviderInit(WDFDEVICE Device, WV_PROVIDER *pProvider)
 {
+	NTSTATUS status;
+
+	status = WorkQueueInit(&pProvider->WorkQueue, WdfDeviceWdmGetDeviceObject(Device), 0);
+	if (!NT_SUCCESS(status)) {
+		return status;
+	}
+
 	IndexListInit(&pProvider->DevIndex);
 	IndexListInit(&pProvider->CqIndex);
 	IndexListInit(&pProvider->PdIndex);
@@ -72,6 +80,7 @@ void WvProviderInit(WDFDEVICE Device, WV
 	KeInitializeEvent(&pProvider->SharedEvent, NotificationEvent, FALSE);
 	pProvider->Exclusive = 0;
 	KeInitializeEvent(&pProvider->ExclusiveEvent, SynchronizationEvent, FALSE);
+	return STATUS_SUCCESS;
 }
 
 void WvProviderCleanup(WV_PROVIDER *pProvider)
@@ -136,6 +145,7 @@ void WvProviderCleanup(WV_PROVIDER *pPro
 	IndexListDestroy(&pProvider->PdIndex);
 	IndexListDestroy(&pProvider->CqIndex);
 	IndexListDestroy(&pProvider->DevIndex);
+	WorkQueueDestroy(&pProvider->WorkQueue);
 }
 
 // See comment above WvProviderRemoveHandler.
diff -up -r -X \mshefty\scm\winof\trunk\docs\dontdiff.txt -I '\$Id:' trunk\core\winverbs/kernel/wv_provider.h
branches\winverbs\core\winverbs/kernel/wv_provider.h
--- trunk\core\winverbs/kernel/wv_provider.h	2009-01-24 11:41:22.140625000 -0800
+++ branches\winverbs\core\winverbs/kernel/wv_provider.h	2009-05-26 11:57:01.316897300 -0700
@@ -36,6 +36,7 @@
 #include <wdf.h>
 #include <wdm.h>
 
+#include "work_queue.h"
 #include <complib\cl_qmap.h>
 #include "wv_driver.h"
 #include "index_list.h"
@@ -64,11 +65,15 @@ typedef struct _WV_PROVIDER
 	LONG			Exclusive;
 	KEVENT			ExclusiveEvent;
 
+	WORK_QUEUE		WorkQueue;
+
 }	WV_PROVIDER;
 
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WV_PROVIDER, WvProviderGetContext)
+
 void WvProviderGet(WV_PROVIDER *pProvider);
 void WvProviderPut(WV_PROVIDER *pProvider);
-void WvProviderInit(WDFDEVICE Device, WV_PROVIDER *pProvider);
+NTSTATUS WvProviderInit(WDFDEVICE Device, WV_PROVIDER *pProvider);
 void WvProviderCleanup(WV_PROVIDER *pProvider);
 
 void WvProviderRemoveHandler(WV_PROVIDER *pProvider, WV_RDMA_DEVICE *pDevice);
diff -up -r -X \mshefty\scm\winof\trunk\docs\dontdiff.txt -I '\$Id:' trunk\core\winverbs/user/wv_ep.cpp
branches\winverbs\core\winverbs/user/wv_ep.cpp
--- trunk\core\winverbs/user/wv_ep.cpp	2009-03-25 12:11:40.637466100 -0700
+++ branches\winverbs\core\winverbs/user/wv_ep.cpp	2009-05-18 18:04:11.438130700 -0700
@@ -339,13 +339,27 @@ Accept(IWVConnectQueuePair* pQp, WV_CONN
 }
 
 STDMETHODIMP CWVConnectEndpoint::
-Disconnect(void)
+Disconnect(IWVConnectQueuePair* pQp, OVERLAPPED* pOverlapped)
 {
-	DWORD		bytes;
-	HRESULT		hr;
+	CWVConnectQueuePair	*qp = (CWVConnectQueuePair *) pQp;
+	WV_IO_EP_DISCONNECT	attr;
+	DWORD				bytes;
+	HRESULT				hr;
+	void				*pout;
+	DWORD				size;
+
+	attr.Id = m_Id;
+	if (pQp != NULL) {
+		attr.QpId = qp->m_Id;
+		qp->m_pVerbs->nd_modify_qp(qp->m_hVerbsQp, &pout, &size);
+	} else {
+		attr.QpId = 0;
+		pout = NULL;
+		size = 0;
+	}
 
 	if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_DISCONNECT,
-						  &m_Id, sizeof m_Id, NULL, 0, &bytes, NULL)) {
+						  &attr, sizeof attr, pout, size, &bytes, pOverlapped)) {
 		hr = WV_SUCCESS;
 	} else {
 		hr = HRESULT_FROM_WIN32(GetLastError());
diff -up -r -X \mshefty\scm\winof\trunk\docs\dontdiff.txt -I '\$Id:' trunk\core\winverbs/user/wv_ep.h
branches\winverbs\core\winverbs/user/wv_ep.h
--- trunk\core\winverbs/user/wv_ep.h	2008-12-01 12:41:07.938683200 -0800
+++ branches\winverbs\core\winverbs/user/wv_ep.h	2009-05-18 14:14:09.218872800 -0700
@@ -61,7 +61,7 @@ public:
 						 WV_CONNECT_PARAM* pParam, OVERLAPPED* pOverlapped);
 	STDMETHODIMP Accept(IWVConnectQueuePair* pQp, WV_CONNECT_PARAM* pParam,
 						OVERLAPPED* pOverlapped);
-	STDMETHODIMP Disconnect();
+	STDMETHODIMP Disconnect(IWVConnectQueuePair* pQp, OVERLAPPED* pOverlapped);
 	STDMETHODIMP NotifyDisconnect(OVERLAPPED* pOverlapped);
 	STDMETHODIMP Query(WV_CONNECT_ATTRIBUTES* pAttributes);
 
diff -up -r -X \mshefty\scm\winof\trunk\docs\dontdiff.txt -I '\$Id:' trunk\core\winverbs/wv_ioctl.h
branches\winverbs\core\winverbs/wv_ioctl.h
--- trunk\core\winverbs/wv_ioctl.h	2009-03-27 03:04:48.793750000 -0700
+++ branches\winverbs\core\winverbs/wv_ioctl.h	2009-05-18 15:43:44.348140100 -0700
@@ -272,7 +272,7 @@ enum {
 #define WV_IOCTL_EP_ACCEPT				WV_IOCTL(WV_IO_FUNCTION_BASE + \
 												 WV_IO_FUNCTION_EP_ACCEPT)
 
-// UINT64 Id / none
+// WV_IO_EP_DISCONNECT/ verbs specific
 #define WV_IOCTL_EP_DISCONNECT			WV_IOCTL(WV_IO_FUNCTION_BASE + \
 												 WV_IO_FUNCTION_EP_DISCONNECT)
 
@@ -737,4 +737,11 @@ typedef struct _WV_IO_EP_ATTRIBUTES
 
 }	WV_IO_EP_ATTRIBUTES;
 
+typedef struct _WV_IO_EP_DISCONNECT
+{
+	UINT64					Id;
+	UINT64					QpId;
+
+}	WV_IO_EP_DISCONNECT;
+
 #endif // _WV_IOCTL_H_
Only in branches\winverbs\inc\kernel\rdma: _ntstatus_.h
diff -up -r -X \mshefty\scm\winof\trunk\docs\dontdiff.txt -I '\$Id:' trunk\inc\user\rdma/winverbs.h
branches\winverbs\inc\user\rdma/winverbs.h
--- trunk\inc\user\rdma/winverbs.h	2009-03-27 03:05:27.028125000 -0700
+++ branches\winverbs\inc\user\rdma/winverbs.h	2009-05-18 15:46:31.724211300 -0700
@@ -1156,9 +1156,9 @@ DECLARE_INTERFACE_(IWVEndpoint, IWVOverl
 
 #undef INTERFACE
 #define INTERFACE IWVConnectEndpoint
-// {ac670274-1934-4759-a39c-eee01a8130b3}
-DEFINE_GUID(IID_IWVConnectEndpoint, 0xac670274, 0x1934, 0x4759,
-			0xa3, 0x9c, 0xee, 0xe0, 0x1a, 0x81, 0x30, 0xb3);
+// {B7C6708E-EA9C-4cff-B2CF-35BCA9A3739A}
+DEFINE_GUID(IID_IWVConnectEndpoint, 0xb7c6708e, 0xea9c, 0x4cff,
+			0xb2, 0xcf, 0x35, 0xbc, 0xa9, 0xa3, 0x73, 0x9a);
 
 DECLARE_INTERFACE_(IWVConnectEndpoint, IWVEndpoint)
 {
@@ -1236,7 +1236,9 @@ DECLARE_INTERFACE_(IWVConnectEndpoint, I
 		) PURE;
 
 	STDMETHOD(Disconnect)(
-		THIS
+		THIS_
+		__in_opt IWVConnectQueuePair* pQp,
+		__in_opt OVERLAPPED* pOverlapped
 		) PURE;
 
 	STDMETHOD(NotifyDisconnect)(





More information about the ofw mailing list