From fd1839af3a13ecc61522343839ebff58ea921e8e Mon Sep 17 00:00:00 2001 From: shefty Date: Tue, 9 Jun 2009 16:40:24 +0000 Subject: [PATCH] winverbs: process connect and accept asynchronously Allow processing of EP:Connect and EP:Accept calls asynchronously. The librdmacm uses events to report the completion of rdma_connect and rdma_accept calls, which allows users of that interface to take advantage of asynchronous operation. Modify the winverbs kernel driver to queue connect/accept calls to a system thread for better parallelism. This improves the measured connection rate of rdma_cmatose by 3%. The connection rate includes address resolution, route resolution, PD/CQ/QP creation and state transitions, memory registration, posting of receive buffers, and CM message exchanges. This patch effectively only improves the parallelism of modify QP. Signed-off-by: Sean Hefty git-svn-id: svn://openib.tc.cornell.edu/gen1@2240 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86 --- trunk/core/winverbs/kernel/wv_ep.c | 57 ++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/trunk/core/winverbs/kernel/wv_ep.c b/trunk/core/winverbs/kernel/wv_ep.c index 964cc3bb..ab7ef666 100644 --- a/trunk/core/winverbs/kernel/wv_ep.c +++ b/trunk/core/winverbs/kernel/wv_ep.c @@ -409,7 +409,6 @@ static NTSTATUS WvEpDisconnectQp(WV_PROVIDER *pProvider, UINT64 QpId, static void WvEpDisconnectHandler(WORK_ENTRY *pWork) { - WORK_ENTRY *work; WV_PROVIDER *prov; WDFREQUEST request; WV_IO_EP_DISCONNECT *pattr; @@ -543,8 +542,10 @@ static NTSTATUS WvEpIbCmHandler(iba_cm_id *pId, iba_cm_event *pEvent) return STATUS_SUCCESS; } -void WvEpConnect(WV_PROVIDER *pProvider, WDFREQUEST Request) +void WvEpConnectHandler(WORK_ENTRY *pWork) { + WV_PROVIDER *prov; + WDFREQUEST request; WV_IO_EP_CONNECT *pattr; WV_ENDPOINT *ep; WV_QUEUE_PAIR *qp; @@ -552,7 +553,10 @@ void WvEpConnect(WV_PROVIDER *pProvider, WDFREQUEST Request) NTSTATUS status; UINT8 data[IB_REQ_PDATA_SIZE]; - status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_EP_CONNECT), + request = (WDFREQUEST) pWork->Context; + prov = WvProviderGetContext(WdfRequestGetFileObject(request)); + + status = WdfRequestRetrieveInputBuffer(request, sizeof(WV_IO_EP_CONNECT), &pattr, NULL); if (!NT_SUCCESS(status)) { goto complete; @@ -563,13 +567,13 @@ void WvEpConnect(WV_PROVIDER *pProvider, WDFREQUEST Request) goto complete; } - ep = WvEpAcquire(pProvider, pattr->Id); + ep = WvEpAcquire(prov, pattr->Id); if (ep == NULL) { status = STATUS_NOT_FOUND; goto complete; } - qp = WvQpAcquire(pProvider, pattr->QpId); + qp = WvQpAcquire(prov, pattr->QpId); if (qp == NULL) { status = STATUS_NOT_FOUND; goto release; @@ -617,7 +621,7 @@ void WvEpConnect(WV_PROVIDER *pProvider, WDFREQUEST Request) ep->State = WvEpActiveConnect; status = IbCmInterface.CM.send_req(ep->pIbCmId, &req); if (NT_SUCCESS(status)) { - status = WdfRequestForwardToIoQueue(Request, ep->Queue); + status = WdfRequestForwardToIoQueue(request, ep->Queue); } if (!NT_SUCCESS(status)) { @@ -629,10 +633,25 @@ release: WvEpRelease(ep); complete: if (!NT_SUCCESS(status)) { - WdfRequestComplete(Request, status); + WdfRequestComplete(request, status); } } +static void WvEpProcessAsync(WV_PROVIDER *pProvider, WDFREQUEST Request, + void (*AsyncHandler)(struct _WORK_ENTRY *Work)) +{ + WORK_ENTRY *work; + + work = WorkEntryFromIrp(WdfRequestWdmGetIrp(Request)); + WorkEntryInit(work, AsyncHandler, Request); + WorkQueueInsert(&pProvider->WorkQueue, work); +} + +void WvEpConnect(WV_PROVIDER *pProvider, WDFREQUEST Request) +{ + WvEpProcessAsync(pProvider, Request, WvEpConnectHandler); +} + static NTSTATUS WvEpModifyQpRtr(WV_ENDPOINT *pEndpoint, WV_QUEUE_PAIR *pQp, UINT64 ResponderResources, UINT32 Psn, UINT8 *pVerbsData, UINT32 VerbsSize) @@ -792,21 +811,26 @@ out: return status; } -void WvEpAccept(WV_PROVIDER *pProvider, WDFREQUEST Request) +void WvEpAcceptHandler(WORK_ENTRY *pWork) { + WV_PROVIDER *prov; + WDFREQUEST request; WV_IO_EP_ACCEPT *pattr; WV_ENDPOINT *ep; NTSTATUS status; UINT8 *out; size_t outlen; - status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_EP_ACCEPT), + request = (WDFREQUEST) pWork->Context; + prov = WvProviderGetContext(WdfRequestGetFileObject(request)); + + status = WdfRequestRetrieveInputBuffer(request, sizeof(WV_IO_EP_ACCEPT), &pattr, NULL); if (!NT_SUCCESS(status)) { goto complete; } - status = WdfRequestRetrieveOutputBuffer(Request, 0, &out, &outlen); + status = WdfRequestRetrieveOutputBuffer(request, 0, &out, &outlen); if (!NT_SUCCESS(status) && status != STATUS_BUFFER_TOO_SMALL) { goto complete; } @@ -816,7 +840,7 @@ void WvEpAccept(WV_PROVIDER *pProvider, WDFREQUEST Request) goto complete; } - ep = WvEpAcquire(pProvider, pattr->Id); + ep = WvEpAcquire(prov, pattr->Id); if (ep == NULL) { status = STATUS_NOT_FOUND; goto complete; @@ -825,10 +849,10 @@ void WvEpAccept(WV_PROVIDER *pProvider, WDFREQUEST Request) /* EP state is re-checked under lock in WvEpAccept* calls */ switch (ep->State) { case WvEpActiveConnect: - status = WvEpAcceptActive(Request, out, outlen, ep, pattr); + status = WvEpAcceptActive(request, out, outlen, ep, pattr); break; case WvEpPassiveConnect: - status = WvEpAcceptPassive(Request, out, outlen, ep, pattr); + status = WvEpAcceptPassive(request, out, outlen, ep, pattr); break; default: status = STATUS_NOT_SUPPORTED; @@ -838,10 +862,15 @@ void WvEpAccept(WV_PROVIDER *pProvider, WDFREQUEST Request) WvEpRelease(ep); complete: if (!NT_SUCCESS(status)) { - WdfRequestComplete(Request, status); + WdfRequestComplete(request, status); } } +void WvEpAccept(WV_PROVIDER *pProvider, WDFREQUEST Request) +{ + WvEpProcessAsync(pProvider, Request, WvEpAcceptHandler); +} + void WvEpReject(WV_PROVIDER *pProvider, WDFREQUEST Request) { WV_IO_ID *id; -- 2.41.0