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 <[EMAIL PROTECTED]>
---
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_


_______________________________________________
ofw mailing list
[email protected]
http://lists.openfabrics.org/cgi-bin/mailman/listinfo/ofw

Reply via email to