[ofw] [PATCH] [RFC] winverbs/srq: add asynchronous notification support
Sean Hefty
sean.hefty at intel.com
Wed Apr 30 20:56:12 PDT 2008
Initial implementation for SRQ asynchronous notification handling. This includes
SRQ errors, limit reached events, and last wqe reached events. Canceling notification
is included.
Signed-off-by: Sean Hefty <sean.hefty at intel.com>
---
Index: core/winverbs/kernel/wv_driver.c
===================================================================
--- core/winverbs/kernel/wv_driver.c (revision 1099)
+++ core/winverbs/kernel/wv_driver.c (working copy)
@@ -254,12 +254,10 @@
WvSrqModify(prov, Request);
break;
case WV_IOCTL_SRQ_NOTIFY:
- //WvSrqNotify(prov, Request);
- WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
+ WvSrqNotify(prov, Request);
break;
case WV_IOCTL_SRQ_CANCEL:
- //WvSrqCancel(prov, Request);
- WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
+ WvSrqCancel(prov, Request);
break;
case WV_IOCTL_QP_CREATE:
WvQpCreate(prov, Request);
Index: core/winverbs/kernel/wv_srq.c
===================================================================
--- core/winverbs/kernel/wv_srq.c (revision 1090)
+++ core/winverbs/kernel/wv_srq.c (working copy)
@@ -27,6 +27,7 @@
* SOFTWARE.
*/
+#include "wv_driver.h"
#include "wv_srq.h"
#include "wv_ioctl.h"
@@ -74,9 +75,34 @@
pVerbsAttr->srq_limit = pAttr->SrqLimit;
}
+static NTSTATUS WvSrqCompleteRequest(WV_SHARED_RECEIVE_QUEUE *pSrq, NTSTATUS Status)
+{
+ WDFREQUEST request;
+ NTSTATUS stat;
+
+ WdfObjectAcquireLock(pSrq->Queue);
+ stat = WdfIoQueueRetrieveNextRequest(pSrq->Queue, &request);
+ WdfObjectReleaseLock(pSrq->Queue);
+
+ if (NT_SUCCESS(stat)) {
+ WdfRequestComplete(request, Status);
+ }
+ return stat;
+}
+
static void WvSrqEventHandler(ib_event_rec_t *pEvent)
{
- pEvent;
+ switch (pEvent->type) {
+ case IB_AE_SRQ_LIMIT_REACHED:
+ WvSrqCompleteRequest(pEvent->context, STATUS_ALERTED);
+ break;
+ case IB_AE_SRQ_QP_LAST_WQE_REACHED:
+ WvSrqCompleteRequest(pEvent->context, STATUS_NOTIFY_CLEANUP);
+ break;
+ default:
+ WvSrqCompleteRequest(pEvent->context, STATUS_UNEXPECTED_IO_ERROR);
+ break;
+ }
}
static NTSTATUS WvSrqAlloc(WV_PROTECTION_DOMAIN *pPd, WV_IO_SRQ_ATTRIBUTES *pAttr,
@@ -85,8 +111,10 @@
WV_SHARED_RECEIVE_QUEUE *srq;
ib_srq_attr_t attr;
ib_api_status_t ib_status;
+ NTSTATUS status;
+ WDF_IO_QUEUE_CONFIG config;
- srq = ExAllocatePoolWithTag(PagedPool, sizeof(WV_SHARED_RECEIVE_QUEUE), 'rsvw');
+ srq = ExAllocatePoolWithTag(NonPagedPool, sizeof(WV_SHARED_RECEIVE_QUEUE), 'rsvw');
if (srq == NULL) {
return STATUS_NO_MEMORY;
}
@@ -94,11 +122,18 @@
srq->Ref = 1;
KeInitializeEvent(&srq->Event, NotificationEvent, FALSE);
+ WDF_IO_QUEUE_CONFIG_INIT(&config, WdfIoQueueDispatchManual);
+ status = WdfIoQueueCreate(ControlDevice, &config,
+ WDF_NO_OBJECT_ATTRIBUTES, &srq->Queue);
+ if (!NT_SUCCESS(status)) {
+ goto err1;
+ }
+
WvVerbsConvertSrq(&attr, pAttr);
ib_status = pPd->pVerbs->create_srq(pPd->hVerbsPd, srq, WvSrqEventHandler,
&attr, &srq->hVerbsSrq, pVerbsData);
if (ib_status != IB_SUCCESS) {
- goto err;
+ goto err2;
}
srq->pPd = pPd;
@@ -107,7 +142,9 @@
*ppSrq = srq;
return STATUS_SUCCESS;
-err:
+err2:
+ WdfObjectDelete(srq->Queue);
+err1:
ExFreePool(srq);
return STATUS_UNSUCCESSFUL;
}
@@ -211,6 +248,8 @@
pSrq->pVerbs->destroy_srq(pSrq->hVerbsSrq);
}
+ WdfIoQueuePurgeSynchronously(pSrq->Queue);
+ WdfObjectDelete(pSrq->Queue);
WvPdPut(pSrq->pPd);
ExFreePool(pSrq);
}
@@ -297,4 +336,58 @@
len = outlen;
complete:
WdfRequestCompleteWithInformation(Request, status, len);
-}
\ No newline at end of file
+}
+
+void WvSrqNotify(WV_PROVIDER *pProvider, WDFREQUEST Request)
+{
+ UINT64 *id;
+ WV_SHARED_RECEIVE_QUEUE *srq;
+ NTSTATUS status;
+
+ status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);
+ if (!NT_SUCCESS(status)) {
+ goto out;
+ }
+
+ srq = WvSrqAcquire(pProvider, *id);
+ if (srq == NULL) {
+ status = STATUS_NOT_FOUND;
+ goto out;
+ }
+
+ WdfObjectAcquireLock(srq->Queue);
+ status = WdfRequestForwardToIoQueue(Request, srq->Queue);
+ WdfObjectReleaseLock(srq->Queue);
+ WvSrqRelease(srq);
+
+out:
+ if (!NT_SUCCESS(status)) {
+ WdfRequestComplete(Request, status);
+ }
+}
+
+void WvSrqCancel(WV_PROVIDER *pProvider, WDFREQUEST Request)
+{
+ UINT64 *id;
+ WV_SHARED_RECEIVE_QUEUE *srq;
+ NTSTATUS status;
+
+ status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);
+ if (!NT_SUCCESS(status)) {
+ goto out;
+ }
+
+ srq = WvSrqAcquire(pProvider, *id);
+ if (srq == NULL) {
+ status = STATUS_NOT_FOUND;
+ goto out;
+ }
+
+ do {
+ status = WvSrqCompleteRequest(srq, STATUS_CANCELLED);
+ } while (NT_SUCCESS(status));
+ WvSrqRelease(srq);
+
+out:
+ WdfRequestComplete(Request, status);
+}
Index: core/winverbs/kernel/wv_srq.h
===================================================================
--- core/winverbs/kernel/wv_srq.h (revision 1075)
+++ core/winverbs/kernel/wv_srq.h (working copy)
@@ -50,6 +50,7 @@
KEVENT Event;
LONG Ref;
+ WDFQUEUE Queue;
} WV_SHARED_RECEIVE_QUEUE;
@@ -64,5 +65,7 @@
void WvSrqModify(WV_PROVIDER *pProvider, WDFREQUEST Request);
void WvSrqQuery(WV_PROVIDER *pProvider, WDFREQUEST Request);
+void WvSrqNotify(WV_PROVIDER *pProvider, WDFREQUEST Request);
+void WvSrqCancel(WV_PROVIDER *pProvider, WDFREQUEST Request);
#endif // _WV_SRQ_H_
More information about the ofw
mailing list