[ofw] [PATCH] [RFC] winverbs/qp: add multicast support

Sean Hefty sean.hefty at intel.com
Thu May 1 00:27:58 PDT 2008


Initial implementation of QP attach/detach routines.  Because the CI does
not support asynchronous operation, the current behavior is synchronous.

The implementation is optimized assuming that a single QP will only be
attached to a handful of multicast groups.

Signed-off-by: Sean Hefty <sean.hefty at intel.com>
---
Index: core/winverbs/kernel/wv_driver.c
===================================================================
--- core/winverbs/kernel/wv_driver.c	(revision 1102)
+++ core/winverbs/kernel/wv_driver.c	(working copy)
@@ -273,12 +273,10 @@
 		WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
 		break;
 	case WV_IOCTL_QP_ATTACH:
-		//WvQpAttach(prov, Request);
-		WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
+		WvQpAttach(prov, Request);
 		break;
 	case WV_IOCTL_QP_DETACH:
-		//WvQpDetach(prov, Request);
-		WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
+		WvQpDetach(prov, Request);
 		break;
 	case WV_IOCTL_QP_CANCEL:
 		WvQpCancel(prov, Request);
Index: core/winverbs/kernel/wv_pd.c
===================================================================
--- core/winverbs/kernel/wv_pd.c	(revision 1076)
+++ core/winverbs/kernel/wv_pd.c	(working copy)
@@ -250,8 +250,7 @@
 
 	for (entry = pPd->QpList.Flink; entry != &pPd->QpList; entry = entry->Flink) {
 		qp = CONTAINING_RECORD(entry, WV_QUEUE_PAIR, Entry);
-		pPd->pVerbs->destroy_qp(qp->hVerbsQp, 0);
-		qp->hVerbsQp = NULL;
+		WvQpRemoveHandler(qp);
 	}
 
 	for (entry = pPd->SrqList.Flink; entry != &pPd->SrqList; entry = entry->Flink) {
Index: core/winverbs/kernel/wv_qp.c
===================================================================
--- core/winverbs/kernel/wv_qp.c	(revision 1102)
+++ core/winverbs/kernel/wv_qp.c	(working copy)
@@ -30,6 +30,15 @@
 #include "wv_qp.h"
 #include "wv_ioctl.h"
 
+typedef struct _WV_MULTICAST
+{
+	LIST_ENTRY			Entry;
+	WV_IO_GID			Gid;
+	UINT16				Lid;
+	ib_mcast_handle_t	hVerbsMc;
+
+}	WV_MULTICAST;
+
 static void WvVerbsConvertCreate(ib_qp_create_t *pVerbsAttr,
 								 WV_IO_QP_CREATE *pAttr, WV_QUEUE_PAIR *pQp)
 {
@@ -254,6 +263,7 @@
 
 	qp->Ref = 1;
 	KeInitializeEvent(&qp->Event, NotificationEvent, FALSE);
+	InitializeListHead(&qp->McList);
 	status = WvQpCreateAcquire(pProvider, qp, attr);
 	if (!NT_SUCCESS(status)) {
 		goto err2;
@@ -328,6 +338,18 @@
 
 void WvQpFree(WV_QUEUE_PAIR *pQp)
 {
+	WV_MULTICAST		*mc;
+	LIST_ENTRY			*entry;
+
+	while ((entry = RemoveHeadList(&pQp->McList)) != &pQp->McList) {
+		mc = CONTAINING_RECORD(entry, WV_MULTICAST, Entry);
+		if (mc->hVerbsMc != NULL) {
+			pQp->pVerbs->detach_mcast(mc->hVerbsMc);
+		}
+		WvQpPut(pQp);
+		ExFreePool(mc);
+	}
+
 	if (InterlockedDecrement(&pQp->Ref) > 0) {
 		KeWaitForSingleObject(&pQp->Event, Executive, KernelMode, FALSE, NULL);
 	}
@@ -384,6 +406,121 @@
 	WdfRequestCompleteWithInformation(Request, status, len);
 }
 
+void WvQpAttach(WV_PROVIDER *pProvider, WDFREQUEST Request)
+{
+	WV_MULTICAST			*pmc;
+	WV_IO_QP_MULTICAST		*mc;
+	WV_QUEUE_PAIR			*qp;
+	NTSTATUS				status;
+	ib_api_status_t			ib_status;
+
+	status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_QP_MULTICAST),
+										   &mc, NULL);
+	if (!NT_SUCCESS(status)) {
+		goto err1;
+	}
+
+	pmc = ExAllocatePoolWithTag(PagedPool, sizeof(WV_MULTICAST), 'cmvw');
+	if (pmc == NULL) {
+		status = STATUS_NO_MEMORY;
+		goto err1;
+	}
+
+	qp = WvQpAcquire(pProvider, mc->Id.Id);
+	if (qp == NULL) {
+		status = STATUS_NOT_FOUND;
+		goto err2;
+	}
+
+	pmc->Gid = mc->Gid;
+	pmc->Lid = (UINT16) mc->Id.Data;
+	ib_status = qp->pVerbs->attach_mcast(qp->hVerbsQp, (ib_gid_t *) &mc->Gid,
+										 (UINT16) mc->Id.Data, &pmc->hVerbsMc,
NULL);
+
+	if (ib_status != IB_SUCCESS) {
+		status = STATUS_UNSUCCESSFUL;
+		goto err3;
+	}
+
+	KeAcquireGuardedMutex(&qp->pPd->Lock);
+	InsertHeadList(&qp->McList, &pmc->Entry);
+	KeReleaseGuardedMutex(&qp->pPd->Lock);
+
+	WvProviderEnableRemove(pProvider);
+	WdfRequestComplete(Request, STATUS_SUCCESS);
+	return;
+
+err3:
+	WvQpRelease(qp);
+err2:
+	ExFreePool(pmc);
+err1:
+	WdfRequestComplete(Request, status);
+}
+
+void WvQpDetach(WV_PROVIDER *pProvider, WDFREQUEST Request)
+{
+	WV_MULTICAST			*pmc;
+	WV_IO_QP_MULTICAST		*mc;
+	WV_QUEUE_PAIR			*qp;
+	LIST_ENTRY				*entry;
+	NTSTATUS				status;
+
+	status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_QP_MULTICAST),
+										   &mc, NULL);
+	if (!NT_SUCCESS(status)) {
+		goto complete;
+	}
+
+	qp = WvQpAcquire(pProvider, mc->Id.Id);
+	if (qp == NULL) {
+		status = STATUS_NOT_FOUND;
+		goto complete;
+	}
+
+	KeAcquireGuardedMutex(&qp->pPd->Lock);
+	for (entry = qp->McList.Flink; entry != &qp->McList; entry = entry->Flink) {
+		pmc = CONTAINING_RECORD(entry, WV_MULTICAST, Entry);
+
+		if (RtlCompareMemory(&pmc->Gid, &mc->Gid, sizeof(pmc->Gid)) == sizeof(pmc->Gid) &&
+			pmc->Lid == (UINT16) mc->Id.Data) {
+			RemoveEntryList(&pmc->Entry);
+			KeReleaseGuardedMutex(&qp->pPd->Lock);
+
+			if (pmc->hVerbsMc != NULL) {
+				qp->pVerbs->detach_mcast(pmc->hVerbsMc);
+			}
+			WvQpPut(qp);
+			WvQpRelease(qp);
+
+			ExFreePool(pmc);
+			status = STATUS_SUCCESS;
+			goto complete;
+		}
+	}
+	KeReleaseGuardedMutex(&qp->pPd->Lock);
+	WvQpRelease(qp);
+	status = STATUS_NOT_FOUND;
+
+complete:
+	WdfRequestComplete(Request, status);
+}
+
+void WvQpRemoveHandler(WV_QUEUE_PAIR *pQp)
+{
+	WV_MULTICAST		*mc;
+	LIST_ENTRY			*entry;
+
+	for (entry = pQp->McList.Flink; entry != &pQp->McList; entry = entry->Flink) {
+		mc = CONTAINING_RECORD(entry, WV_MULTICAST, Entry);
+		pQp->pVerbs->detach_mcast(mc->hVerbsMc);
+		mc->hVerbsMc = NULL;
+	}
+
+	pQp->pVerbs->destroy_qp(pQp->hVerbsQp, 0);
+	pQp->hVerbsQp = NULL;
+}
+
 void WvQpCancel(WV_PROVIDER *pProvider, WDFREQUEST Request)
 {
 	UINT64				*id;
Index: core/winverbs/kernel/wv_qp.h
===================================================================
--- core/winverbs/kernel/wv_qp.h	(revision 1102)
+++ core/winverbs/kernel/wv_qp.h	(working copy)
@@ -52,6 +52,7 @@
 	ci_interface_t			*pVerbs;
 	ib_qp_handle_t			hVerbsQp;
 	LIST_ENTRY				Entry;
+	LIST_ENTRY				McList;
 
 	KEVENT					Event;
 	LONG					Ref;
@@ -61,14 +62,12 @@
 void WvQpCreate(WV_PROVIDER *pProvider, WDFREQUEST Request);
 void WvQpDestroy(WV_PROVIDER *pProvider, WDFREQUEST Request);
 void WvQpFree(WV_QUEUE_PAIR *pQp);
+void WvQpRemoveHandler(WV_QUEUE_PAIR *pQp);
 
-//void WvQpGet(WV_QUEUE_PAIR *pQp);
-//void WvQpPut(WV_QUEUE_PAIR *pQp);
-
 //void WvQpModify(WV_PROVIDER *pProvider, WDFREQUEST Request);
 void WvQpQuery(WV_PROVIDER *pProvider, WDFREQUEST Request);
-//void WvQpAttach(WV_PROVIDER *pProvider, WDFREQUEST Request);
-//void WvQpDetach(WV_PROVIDER *pProvider, WDFREQUEST Request);
+void WvQpAttach(WV_PROVIDER *pProvider, WDFREQUEST Request);
+void WvQpDetach(WV_PROVIDER *pProvider, WDFREQUEST Request);
 void WvQpCancel(WV_PROVIDER *pProvider, WDFREQUEST Request);
 
 #endif // _WV_QP_H_





More information about the ofw mailing list