[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