\r
void WvEpFree(WV_ENDPOINT *pEndpoint)\r
{\r
+ WdfObjectAcquireLock(pEndpoint->Queue);\r
+ pEndpoint->State = WvEpDestroying;\r
+ WdfObjectReleaseLock(pEndpoint->Queue);\r
+\r
if (pEndpoint->pIbCmId != NULL) {\r
IbCmInterface.CM.destroy_id(pEndpoint->pIbCmId);\r
}\r
pEndpoint->Attributes.Param.Connect.DataLength = len;\r
}\r
\r
+/*\r
+ * The QP transition to error may be done from an async worker thread.\r
+ * Synchronize against application exit.\r
+ */\r
static NTSTATUS WvEpModifyQpErr(WV_QUEUE_PAIR *pQp,\r
UINT8 *pVerbsData, UINT32 VerbsSize)\r
{\r
ib_api_status_t ib_status;\r
NTSTATUS status;\r
\r
+ KeAcquireGuardedMutex(&pQp->Lock);\r
+ if (pQp->hVerbsQp == NULL) {\r
+ status = STATUS_NOT_FOUND;\r
+ goto out;\r
+ }\r
+\r
attr.req_state = IB_QPS_ERROR;\r
ib_status = pQp->pVerbs->ndi_modify_qp(pQp->hVerbsQp, &attr, NULL,\r
VerbsSize, pVerbsData);\r
- if (ib_status != IB_SUCCESS) {\r
- return STATUS_UNSUCCESSFUL;\r
+ if (ib_status == IB_SUCCESS) {\r
+ status = STATUS_SUCCESS;\r
+ } else { \r
+ status = STATUS_UNSUCCESSFUL;\r
}\r
\r
- return STATUS_SUCCESS;\r
+out:\r
+ KeReleaseGuardedMutex(&pQp->Lock);\r
+ return status;\r
}\r
\r
static NTSTATUS WvEpDisconnectQp(WV_PROVIDER *pProvider, UINT64 QpId,\r
\r
complete:\r
WdfRequestCompleteWithInformation(request, status, outlen);\r
+ WvProviderPut(prov);\r
}\r
\r
// We use IRP DriverContext to queue the request for further processing,\r
NTSTATUS status;\r
\r
WdfObjectAcquireLock(pEndpoint->Queue);\r
+ if (pEndpoint->State == WvEpDestroying) {\r
+ goto release;\r
+ }\r
pEndpoint->State = WvEpDisconnected;\r
\r
status = WdfIoQueueRetrieveNextRequest(pEndpoint->Queue, &request);\r
work = WorkEntryFromIrp(WdfRequestWdmGetIrp(request));\r
WdfRequestSetInformation(request, DiscStatus);\r
WorkEntryInit(work, WvEpDisconnectHandler, request);\r
+ WvProviderGet(pEndpoint->pProvider);\r
WorkQueueInsert(&pEndpoint->pProvider->WorkQueue, work);\r
} else {\r
WdfRequestComplete(request, DiscStatus);\r
WdfObjectAcquireLock(pEndpoint->Queue);\r
status = WdfIoQueueRetrieveNextRequest(pEndpoint->Queue, &request);\r
}\r
+release:\r
WdfObjectReleaseLock(pEndpoint->Queue);\r
}\r
\r
if (!NT_SUCCESS(status)) {\r
WdfRequestComplete(request, status);\r
}\r
+ WvProviderPut(prov);\r
}\r
\r
static void WvEpProcessAsync(WV_PROVIDER *pProvider, WDFREQUEST Request,\r
\r
work = WorkEntryFromIrp(WdfRequestWdmGetIrp(Request));\r
WorkEntryInit(work, AsyncHandler, Request);\r
+ WvProviderGet(pProvider);\r
WorkQueueInsert(&pProvider->WorkQueue, work);\r
}\r
\r
if (!NT_SUCCESS(status)) {\r
WdfRequestComplete(request, status);\r
}\r
+ WvProviderPut(prov);\r
}\r
\r
void WvEpAccept(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
qp->pProvider = pProvider;\r
KeInitializeEvent(&qp->Event, NotificationEvent, FALSE);\r
InitializeListHead(&qp->McList);\r
+ KeInitializeGuardedMutex(&qp->Lock);\r
status = WvQpCreateAcquire(pProvider, qp, inattr);\r
if (!NT_SUCCESS(status)) {\r
goto err2;\r
WdfRequestComplete(Request, status);\r
}\r
\r
+/*\r
+ * Synchronize freeing the QP due to application exit with asynchronous\r
+ * disconnect processing transitioning the QP into the error state.\r
+ */\r
void WvQpFree(WV_QUEUE_PAIR *pQp)\r
{\r
WV_MULTICAST *mc;\r
LIST_ENTRY *entry;\r
+ ib_qp_handle_t hqp;\r
+\r
+ KeAcquireGuardedMutex(&pQp->Lock);\r
+ hqp = pQp->hVerbsQp;\r
+ pQp->hVerbsQp = NULL;\r
+ KeReleaseGuardedMutex(&pQp->Lock);\r
\r
while ((entry = RemoveHeadList(&pQp->McList)) != &pQp->McList) {\r
mc = CONTAINING_RECORD(entry, WV_MULTICAST, Entry);\r
KeWaitForSingleObject(&pQp->Event, Executive, KernelMode, FALSE, NULL);\r
}\r
\r
- if (pQp->hVerbsQp != NULL) {\r
- pQp->pVerbs->destroy_qp(pQp->hVerbsQp, 0);\r
+ if (hqp != NULL) {\r
+ pQp->pVerbs->destroy_qp(hqp, 0);\r
}\r
\r
if (pQp->pSrq != NULL) {\r
goto err3;\r
}\r
\r
- KeAcquireGuardedMutex(&qp->pPd->Lock);\r
+ KeAcquireGuardedMutex(&qp->Lock);\r
InsertHeadList(&qp->McList, &pmc->Entry);\r
- KeReleaseGuardedMutex(&qp->pPd->Lock);\r
+ KeReleaseGuardedMutex(&qp->Lock);\r
\r
WvQpRelease(qp);\r
WdfRequestComplete(Request, STATUS_SUCCESS);\r
goto complete;\r
}\r
\r
- KeAcquireGuardedMutex(&qp->pPd->Lock);\r
+ KeAcquireGuardedMutex(&qp->Lock);\r
for (entry = qp->McList.Flink; entry != &qp->McList; entry = entry->Flink) {\r
pmc = CONTAINING_RECORD(entry, WV_MULTICAST, Entry);\r
\r
if (RtlCompareMemory(&pmc->Gid, &mc->Gid, sizeof(pmc->Gid)) == sizeof(pmc->Gid) &&\r
pmc->Lid == (NET16) mc->Id.Data) {\r
RemoveEntryList(&pmc->Entry);\r
- KeReleaseGuardedMutex(&qp->pPd->Lock);\r
+ KeReleaseGuardedMutex(&qp->Lock);\r
\r
if (pmc->hVerbsMc != NULL) {\r
qp->pVerbs->detach_mcast(pmc->hVerbsMc);\r
goto release;\r
}\r
}\r
- KeReleaseGuardedMutex(&qp->pPd->Lock);\r
+ KeReleaseGuardedMutex(&qp->Lock);\r
status = STATUS_NOT_FOUND;\r
\r
release:\r