2 * Copyright (c) 2008 Intel Corporation. All rights reserved.
\r
4 * This software is available to you under the OpenIB.org BSD license
\r
7 * Redistribution and use in source and binary forms, with or
\r
8 * without modification, are permitted provided that the following
\r
9 * conditions are met:
\r
11 * - Redistributions of source code must retain the above
\r
12 * copyright notice, this list of conditions and the following
\r
15 * - Redistributions in binary form must reproduce the above
\r
16 * copyright notice, this list of conditions and the following
\r
17 * disclaimer in the documentation and/or other materials
\r
18 * provided with the distribution.
\r
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV
\r
23 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
\r
24 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\r
25 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
26 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\r
30 #include <ntstatus.h>
\r
32 #include "work_queue.c"
\r
33 #include <rdma\wvstatus.h>
\r
34 #include "wv_driver.h"
\r
35 #include "wv_ioctl.h"
\r
36 #include "wv_provider.h"
\r
37 #include "wv_device.h"
\r
44 void WvProviderGet(WV_PROVIDER *pProvider)
\r
46 InterlockedIncrement(&pProvider->Ref);
\r
49 void WvProviderPut(WV_PROVIDER *pProvider)
\r
51 if (InterlockedDecrement(&pProvider->Ref) == 0) {
\r
52 KeSetEvent(&pProvider->Event, 0, FALSE);
\r
56 NTSTATUS WvProviderInit(WDFDEVICE Device, WV_PROVIDER *pProvider)
\r
60 status = WorkQueueInit(&pProvider->WorkQueue, WdfDeviceWdmGetDeviceObject(Device), 0);
\r
61 if (!NT_SUCCESS(status)) {
\r
65 IndexListInit(&pProvider->DevIndex);
\r
66 IndexListInit(&pProvider->CqIndex);
\r
67 IndexListInit(&pProvider->PdIndex);
\r
68 IndexListInit(&pProvider->SrqIndex);
\r
69 IndexListInit(&pProvider->QpIndex);
\r
70 IndexListInit(&pProvider->MwIndex);
\r
71 IndexListInit(&pProvider->AhIndex);
\r
72 IndexListInit(&pProvider->EpIndex);
\r
74 KeInitializeGuardedMutex(&pProvider->Lock);
\r
76 KeInitializeEvent(&pProvider->Event, NotificationEvent, FALSE);
\r
78 pProvider->Pending = 0;
\r
79 pProvider->Active = 0;
\r
80 KeInitializeEvent(&pProvider->SharedEvent, NotificationEvent, FALSE);
\r
81 pProvider->Exclusive = 0;
\r
82 KeInitializeEvent(&pProvider->ExclusiveEvent, SynchronizationEvent, FALSE);
\r
83 return STATUS_SUCCESS;
\r
86 void WvProviderCleanup(WV_PROVIDER *pProvider)
\r
89 WV_COMPLETION_QUEUE *cq;
\r
90 WV_PROTECTION_DOMAIN *pd;
\r
91 WV_SHARED_RECEIVE_QUEUE *srq;
\r
93 WV_MEMORY_WINDOW *mw;
\r
94 WV_ADDRESS_HANDLE *ah;
\r
98 IndexListForEach(&pProvider->EpIndex, i) {
\r
99 ep = (WV_ENDPOINT *) IndexListAt(&pProvider->EpIndex, i);
\r
100 if (ep->State == WvEpListening) {
\r
101 WvEpCancelListen(ep);
\r
104 while ((ep = IndexListRemoveHead(&pProvider->EpIndex)) != NULL) {
\r
105 RemoveEntryList(&ep->Entry);
\r
108 while ((ah = IndexListRemoveHead(&pProvider->AhIndex)) != NULL) {
\r
109 RemoveEntryList(&ah->Entry);
\r
112 while ((mw = IndexListRemoveHead(&pProvider->MwIndex)) != NULL) {
\r
113 RemoveEntryList(&mw->Entry);
\r
116 while ((qp = IndexListRemoveHead(&pProvider->QpIndex)) != NULL) {
\r
117 RemoveEntryList(&qp->Entry);
\r
120 while ((srq = IndexListRemoveHead(&pProvider->SrqIndex)) != NULL) {
\r
121 RemoveEntryList(&srq->Entry);
\r
124 while ((pd = IndexListRemoveHead(&pProvider->PdIndex)) != NULL) {
\r
125 RemoveEntryList(&pd->Entry);
\r
128 while ((cq = IndexListRemoveHead(&pProvider->CqIndex)) != NULL) {
\r
129 RemoveEntryList(&cq->Entry);
\r
132 while ((dev = IndexListRemoveHead(&pProvider->DevIndex)) != NULL) {
\r
136 if (InterlockedDecrement(&pProvider->Ref) > 0) {
\r
137 KeWaitForSingleObject(&pProvider->Event, Executive, KernelMode, FALSE, NULL);
\r
140 IndexListDestroy(&pProvider->EpIndex);
\r
141 IndexListDestroy(&pProvider->AhIndex);
\r
142 IndexListDestroy(&pProvider->MwIndex);
\r
143 IndexListDestroy(&pProvider->QpIndex);
\r
144 IndexListDestroy(&pProvider->SrqIndex);
\r
145 IndexListDestroy(&pProvider->PdIndex);
\r
146 IndexListDestroy(&pProvider->CqIndex);
\r
147 IndexListDestroy(&pProvider->DevIndex);
\r
148 WorkQueueDestroy(&pProvider->WorkQueue);
\r
151 // See comment above WvProviderRemoveHandler.
\r
152 static void WvProviderLockRemove(WV_PROVIDER *pProvider)
\r
154 KeAcquireGuardedMutex(&pProvider->Lock);
\r
155 pProvider->Exclusive++;
\r
156 KeClearEvent(&pProvider->SharedEvent);
\r
157 while (pProvider->Active > 0) {
\r
158 KeReleaseGuardedMutex(&pProvider->Lock);
\r
159 KeWaitForSingleObject(&pProvider->ExclusiveEvent, Executive, KernelMode,
\r
161 KeAcquireGuardedMutex(&pProvider->Lock);
\r
163 pProvider->Active++;
\r
164 KeReleaseGuardedMutex(&pProvider->Lock);
\r
167 // See comment above WvProviderRemoveHandler.
\r
168 static void WvProviderUnlockRemove(WV_PROVIDER *pProvider)
\r
170 KeAcquireGuardedMutex(&pProvider->Lock);
\r
171 pProvider->Exclusive--;
\r
172 pProvider->Active--;
\r
173 if (pProvider->Exclusive > 0) {
\r
174 KeSetEvent(&pProvider->ExclusiveEvent, 0, FALSE);
\r
175 } else if (pProvider->Pending > 0) {
\r
176 KeSetEvent(&pProvider->SharedEvent, 0, FALSE);
\r
178 KeReleaseGuardedMutex(&pProvider->Lock);
\r
182 * Must hold pProvider->Lock. Function may release and re-acquire.
\r
183 * See comment above WvProviderRemoveHandler.
\r
185 void WvProviderDisableRemove(WV_PROVIDER *pProvider)
\r
187 while (pProvider->Exclusive > 0) {
\r
188 pProvider->Pending++;
\r
189 KeReleaseGuardedMutex(&pProvider->Lock);
\r
190 KeWaitForSingleObject(&pProvider->SharedEvent, Executive, KernelMode,
\r
192 KeAcquireGuardedMutex(&pProvider->Lock);
\r
193 pProvider->Pending--;
\r
195 InterlockedIncrement(&pProvider->Active);
\r
199 * No need to hold pProvider->Lock when releasing.
\r
200 * See comment above WvProviderRemoveHandler.
\r
202 void WvProviderEnableRemove(WV_PROVIDER *pProvider)
\r
204 InterlockedDecrement(&pProvider->Active);
\r
205 if (pProvider->Exclusive > 0) {
\r
206 KeSetEvent(&pProvider->ExclusiveEvent, 0, FALSE);
\r
211 * The remove handler blocks all other threads executing through this
\r
212 * provider until the remove has been processed. Because device removal is
\r
213 * rare, we want a simple, optimized code path for all calls that access
\r
214 * the underlying hardware device, making use of any locks that we would
\r
215 * have to acquire anyway. The locking for exclusive access can be
\r
216 * as ugly and slow as needed.
\r
218 void WvProviderRemoveHandler(WV_PROVIDER *pProvider, WV_RDMA_DEVICE *pDevice)
\r
223 WvProviderLockRemove(pProvider);
\r
224 IndexListForEach(&pProvider->DevIndex, i) {
\r
225 dev = IndexListAt(&pProvider->DevIndex, i);
\r
226 if (dev->pDevice == pDevice) {
\r
227 WvDeviceRemoveHandler(dev);
\r
230 WvProviderUnlockRemove(pProvider);
\r