winverbs: make PD derive from IWVOverlapped
[mirror/winof/.git] / core / winverbs / kernel / wv_pd.c
1 /*\r
2  * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
3  *\r
4  * This software is available to you under the OpenIB.org BSD license\r
5  * below:\r
6  *\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
10  *\r
11  *      - Redistributions of source code must retain the above\r
12  *        copyright notice, this list of conditions and the following\r
13  *        disclaimer.\r
14  *\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
19  *\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
27  * SOFTWARE.\r
28  */\r
29 \r
30 #include "wv_pd.h"\r
31 #include "wv_srq.h"\r
32 #include "wv_qp.h"\r
33 #include "wv_ioctl.h"\r
34 \r
35 void WvPdGet(WV_PROTECTION_DOMAIN *pPd)\r
36 {\r
37         InterlockedIncrement(&pPd->Ref);\r
38 }\r
39 \r
40 void WvPdPut(WV_PROTECTION_DOMAIN *pPd)\r
41 {\r
42         if (InterlockedDecrement(&pPd->Ref) == 0) {\r
43                 KeSetEvent(&pPd->Event, 0, FALSE);\r
44         }\r
45 }\r
46 \r
47 WV_PROTECTION_DOMAIN *WvPdAcquire(WV_PROVIDER *pProvider, UINT64 Id)\r
48 {\r
49         WV_PROTECTION_DOMAIN *pd;\r
50 \r
51         KeAcquireGuardedMutex(&pProvider->Lock);\r
52         WvProviderDisableRemove(pProvider);\r
53         pd = IndexListAt(&pProvider->PdIndex, (SIZE_T) Id);\r
54         if (pd != NULL && pd->hVerbsPd != NULL) {\r
55                 WvPdGet(pd);\r
56         } else {\r
57                 pd = NULL;\r
58                 WvProviderEnableRemove(pProvider);\r
59         }\r
60         KeReleaseGuardedMutex(&pProvider->Lock);\r
61 \r
62         return pd;\r
63 }\r
64 \r
65 void WvPdRelease(WV_PROTECTION_DOMAIN *pPd)\r
66 {\r
67         WvProviderEnableRemove(pPd->pDevice->pProvider);\r
68         WvPdPut(pPd);\r
69 }\r
70 \r
71 static NTSTATUS WvPdAlloc(WV_DEVICE *pDevice, WV_PROTECTION_DOMAIN **ppPd,\r
72                                                   ci_umv_buf_t *pVerbsData)\r
73 {\r
74         ib_api_status_t                 ib_status;\r
75         WV_PROTECTION_DOMAIN    *pd;\r
76 \r
77         pd = ExAllocatePoolWithTag(PagedPool, sizeof(WV_PROTECTION_DOMAIN), 'dpvw');\r
78         if (pd == NULL) {\r
79                 return STATUS_NO_MEMORY;\r
80         }\r
81 \r
82         pd->Ref = 1;\r
83         KeInitializeEvent(&pd->Event, NotificationEvent, FALSE);\r
84         InitializeListHead(&pd->QpList);\r
85         InitializeListHead(&pd->SrqList);\r
86         InitializeListHead(&pd->MwList);\r
87         InitializeListHead(&pd->AhList);\r
88         cl_qmap_init(&pd->MrMap);\r
89         KeInitializeGuardedMutex(&pd->Lock);\r
90 \r
91         ib_status = pDevice->pVerbs->allocate_pd(pDevice->hVerbsDevice, IB_PDT_NORMAL,\r
92                                                                                          &pd->hVerbsPd, pVerbsData);\r
93         if (ib_status != IB_SUCCESS) {\r
94                 goto err;\r
95         }\r
96 \r
97         pd->pDevice = pDevice;\r
98         pd->pVerbs = pDevice->pVerbs;\r
99         *ppPd = pd;\r
100         return STATUS_SUCCESS;\r
101 \r
102 err:\r
103         ExFreePool(pd);\r
104         return STATUS_UNSUCCESSFUL;\r
105 }\r
106 \r
107 void WvPdAllocate(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
108 {\r
109         WV_IO_ID                                *inid, *outid;\r
110         size_t                                  inlen, outlen;\r
111         WV_DEVICE                               *dev;\r
112         WV_PROTECTION_DOMAIN    *pd;\r
113         NTSTATUS                                status;\r
114         ci_umv_buf_t                    verbsData;\r
115 \r
116         status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_ID), &inid, &inlen);\r
117         if (!NT_SUCCESS(status)) {\r
118                 goto err1;\r
119         }\r
120         status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_ID), &outid, &outlen);\r
121         if (!NT_SUCCESS(status)) {\r
122                 goto err1;\r
123         }\r
124 \r
125         dev = WvDeviceAcquire(pProvider, inid->Id);\r
126         if (dev == NULL) {\r
127                 status = STATUS_NO_SUCH_DEVICE;\r
128                 goto err1;\r
129         }\r
130 \r
131         WvInitVerbsData(&verbsData, inid->VerbInfo, inlen - sizeof(WV_IO_ID),\r
132                                         outlen - sizeof(WV_IO_ID), inid + 1);\r
133         status = WvPdAlloc(dev, &pd, &verbsData);\r
134         if (!NT_SUCCESS(status)) {\r
135                 goto err2;\r
136         }\r
137 \r
138         KeAcquireGuardedMutex(&pProvider->Lock);\r
139         outid->Id = IndexListInsertHead(&pProvider->PdIndex, pd);\r
140         if (outid->Id == 0) {\r
141                 status = STATUS_NO_MEMORY;\r
142                 goto err3;\r
143         }\r
144         InsertHeadList(&dev->PdList, &pd->Entry);\r
145         KeReleaseGuardedMutex(&pProvider->Lock);\r
146 \r
147         WvProviderEnableRemove(pProvider);\r
148         outid->VerbInfo = verbsData.status;\r
149         WdfRequestCompleteWithInformation(Request, status, outlen);\r
150         return;\r
151 \r
152 err3:\r
153         KeReleaseGuardedMutex(&pProvider->Lock);\r
154         WvPdFree(pd);\r
155 err2:\r
156         WvDeviceRelease(dev);\r
157 err1:\r
158         WdfRequestComplete(Request, status);\r
159 }\r
160 \r
161 void WvPdDeallocate(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
162 {\r
163         WV_PROTECTION_DOMAIN    *pd;\r
164         UINT64                                  *id;\r
165         NTSTATUS                                status;\r
166 \r
167         status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
168         if (!NT_SUCCESS(status)) {\r
169                 goto out;\r
170         }\r
171 \r
172         KeAcquireGuardedMutex(&pProvider->Lock);\r
173         WvProviderDisableRemove(pProvider);\r
174         pd = IndexListAt(&pProvider->PdIndex, (SIZE_T) *id);\r
175         if (pd == NULL) {\r
176                 status = STATUS_NOT_FOUND;\r
177         } else if (pd->Ref > 1) {\r
178                 status = STATUS_ACCESS_DENIED;\r
179         } else {\r
180                 IndexListRemove(&pProvider->PdIndex, (SIZE_T) *id);\r
181                 RemoveEntryList(&pd->Entry);\r
182                 status = STATUS_SUCCESS;\r
183         }\r
184         KeReleaseGuardedMutex(&pProvider->Lock);\r
185 \r
186         if (NT_SUCCESS(status)) {\r
187                 WvPdFree(pd);\r
188         }\r
189         WvProviderEnableRemove(pProvider);\r
190 out:\r
191         WdfRequestComplete(Request, status);\r
192 }\r
193 \r
194 void WvPdCancel(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
195 {\r
196         WV_PROTECTION_DOMAIN    *pd;\r
197         UINT64                                  *id;\r
198         NTSTATUS                                status;\r
199 \r
200         status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
201         if (!NT_SUCCESS(status)) {\r
202                 goto complete;\r
203         }\r
204 \r
205         pd = WvPdAcquire(pProvider, *id);\r
206         if (pd == NULL) {\r
207                 status = STATUS_NOT_FOUND;\r
208                 goto complete;\r
209         }\r
210 \r
211         // Registration is currently synchronous - nothing to do.\r
212         WvPdRelease(pd);\r
213 \r
214 complete:\r
215         WdfRequestComplete(Request, status);\r
216 }\r
217 \r
218 void WvPdFree(WV_PROTECTION_DOMAIN *pPd)\r
219 {\r
220         WV_MEMORY_REGION        *mr;\r
221         cl_map_item_t           *item;\r
222 \r
223         if (InterlockedDecrement(&pPd->Ref) > 0) {\r
224                 KeWaitForSingleObject(&pPd->Event, Executive, KernelMode, FALSE, NULL);\r
225         }\r
226 \r
227         for (item = cl_qmap_head(&pPd->MrMap); item != cl_qmap_end(&pPd->MrMap);\r
228                  item = cl_qmap_head(&pPd->MrMap)) {\r
229                 mr = CONTAINING_RECORD(item, WV_MEMORY_REGION, Item);\r
230                 if (mr->hVerbsMr != NULL) {\r
231                         pPd->pVerbs->deregister_mr(mr->hVerbsMr);\r
232                 }\r
233 \r
234                 cl_qmap_remove_item(&pPd->MrMap, &mr->Item);\r
235                 ExFreePool(mr);\r
236         }\r
237 \r
238         if (pPd->hVerbsPd != NULL) {\r
239                 pPd->pVerbs->deallocate_pd(pPd->hVerbsPd);\r
240         }\r
241 \r
242         WvDevicePut(pPd->pDevice);\r
243         ExFreePool(pPd);\r
244 }\r
245 \r
246 void WvPdRemoveHandler(WV_PROTECTION_DOMAIN *pPd)\r
247 {\r
248         WV_QUEUE_PAIR                   *qp;\r
249         WV_SHARED_RECEIVE_QUEUE *srq;\r
250         WV_MEMORY_REGION                *mr;\r
251         WV_ADDRESS_HANDLE               *ah;\r
252         WV_MEMORY_WINDOW                *mw;\r
253         cl_map_item_t                   *item;\r
254         LIST_ENTRY                              *entry;\r
255 \r
256         for (entry = pPd->MwList.Flink; entry != &pPd->MwList; entry = entry->Flink) {\r
257                 mw = CONTAINING_RECORD(entry, WV_MEMORY_WINDOW, Entry);\r
258                 pPd->pVerbs->destroy_mw(mw->hVerbsMw);\r
259                 mw->hVerbsMw = NULL;\r
260         }\r
261 \r
262         for (entry = pPd->AhList.Flink; entry != &pPd->AhList; entry = entry->Flink) {\r
263                 ah = CONTAINING_RECORD(entry, WV_ADDRESS_HANDLE, Entry);\r
264                 pPd->pVerbs->destroy_av(ah->hVerbsAh);\r
265                 ah->hVerbsAh = NULL;\r
266         }\r
267 \r
268         for (item = cl_qmap_head(&pPd->MrMap); item != cl_qmap_end(&pPd->MrMap);\r
269                  item = cl_qmap_next(item)) {\r
270                 mr = CONTAINING_RECORD(item, WV_MEMORY_REGION, Item);\r
271                 pPd->pVerbs->deregister_mr(mr->hVerbsMr);\r
272                 mr->hVerbsMr = NULL;\r
273         }\r
274 \r
275         for (entry = pPd->QpList.Flink; entry != &pPd->QpList; entry = entry->Flink) {\r
276                 qp = CONTAINING_RECORD(entry, WV_QUEUE_PAIR, Entry);\r
277                 WvQpRemoveHandler(qp);\r
278         }\r
279 \r
280         for (entry = pPd->SrqList.Flink; entry != &pPd->SrqList; entry = entry->Flink) {\r
281                 srq = CONTAINING_RECORD(entry, WV_SHARED_RECEIVE_QUEUE, Entry);\r
282                 pPd->pVerbs->destroy_srq(srq->hVerbsSrq);\r
283                 srq->hVerbsSrq = NULL;\r
284                 srq->pVerbs = NULL;\r
285         }\r
286 \r
287         pPd->pVerbs->deallocate_pd(pPd->hVerbsPd);\r
288         pPd->pVerbs = NULL;\r
289         pPd->hVerbsPd = NULL;\r
290 }\r
291 \r
292 void WvMrRegister(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
293 {\r
294         WV_IO_MEMORY_REGISTER   *reg;\r
295         WV_IO_MEMORY_KEYS               *keys;\r
296         WV_PROTECTION_DOMAIN    *pd;\r
297         WV_MEMORY_REGION                *mr;\r
298         ib_mr_create_t                  attr;\r
299         NTSTATUS                                status;\r
300         ib_api_status_t                 ib_status;\r
301 \r
302         status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_MEMORY_REGISTER),\r
303                                                                                    &reg, NULL);\r
304         if (!NT_SUCCESS(status)) {\r
305                 goto err1;\r
306         }\r
307         status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_MEMORY_KEYS),\r
308                                                                                         &keys, NULL);\r
309         if (!NT_SUCCESS(status)) {\r
310                 goto err1;\r
311         }\r
312 \r
313         pd = WvPdAcquire(pProvider, reg->Id);\r
314         if (pd == NULL) {\r
315                 status = STATUS_NOT_FOUND;\r
316                 goto err1;\r
317         }\r
318 \r
319         mr = ExAllocatePoolWithTag(PagedPool, sizeof(WV_MEMORY_REGION), 'rmvw');\r
320         if (mr == NULL) {\r
321                 status = STATUS_NO_MEMORY;\r
322                 goto err2;\r
323         }\r
324 \r
325         attr.access_ctrl = reg->AccessFlags;\r
326         attr.length = reg->BufferLength;\r
327         attr.vaddr = (void *) (ULONG_PTR) reg->Address;\r
328         ib_status = pd->pVerbs->register_mr(pd->hVerbsPd, &attr, &keys->Lkey,\r
329                                                                                 &keys->Rkey, &mr->hVerbsMr, TRUE);\r
330         if (ib_status != IB_SUCCESS) {\r
331                 status = STATUS_UNSUCCESSFUL;\r
332                 goto err3;\r
333         }\r
334 \r
335         KeAcquireGuardedMutex(&pd->Lock);\r
336         cl_qmap_insert(&pd->MrMap, keys->Lkey, &mr->Item);\r
337         KeReleaseGuardedMutex(&pd->Lock);\r
338 \r
339         WvPdRelease(pd);\r
340         WdfRequestCompleteWithInformation(Request, status, sizeof(WV_IO_MEMORY_KEYS));\r
341         return;\r
342 \r
343 err3:\r
344         ExFreePool(mr);\r
345 err2:\r
346         WvPdRelease(pd);\r
347 err1:\r
348         WdfRequestComplete(Request, status);\r
349 }\r
350 \r
351 void WvMrDeregister(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
352 {\r
353         WV_IO_ID                                *id;\r
354         WV_PROTECTION_DOMAIN    *pd;\r
355         WV_MEMORY_REGION                *mr;\r
356         cl_map_item_t                   *item;\r
357         NTSTATUS                                status;\r
358         ib_api_status_t                 ib_status;\r
359 \r
360         status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_ID), &id, NULL);\r
361         if (!NT_SUCCESS(status)) {\r
362                 goto complete;\r
363         }\r
364 \r
365         pd = WvPdAcquire(pProvider, id->Id);\r
366         if (pd == NULL) {\r
367                 status = STATUS_NOT_FOUND;\r
368                 goto complete;\r
369         }\r
370 \r
371         KeAcquireGuardedMutex(&pd->Lock);\r
372         item = cl_qmap_remove(&pd->MrMap, id->Data);\r
373         KeReleaseGuardedMutex(&pd->Lock);\r
374 \r
375         if (item == cl_qmap_end(&pd->MrMap)) {\r
376                 status = STATUS_NOT_FOUND;\r
377                 goto release;\r
378         }\r
379 \r
380         mr = CONTAINING_RECORD(item, WV_MEMORY_REGION, Item);\r
381 \r
382         ib_status = pd->pVerbs->deregister_mr(mr->hVerbsMr);\r
383         if (ib_status != IB_SUCCESS) {\r
384                 status = STATUS_UNSUCCESSFUL;\r
385                 KeAcquireGuardedMutex(&pd->Lock);\r
386                 cl_qmap_insert(&pd->MrMap, id->Data, &mr->Item);\r
387                 KeReleaseGuardedMutex(&pd->Lock);\r
388                 goto release;\r
389         }\r
390 \r
391         ExFreePool(mr);\r
392 release:\r
393         WvPdRelease(pd);\r
394 complete:\r
395         WdfRequestComplete(Request, status);\r
396 }\r
397 \r
398 void WvMwAllocate(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
399 {\r
400         WV_IO_ID                                *inid, *outid;\r
401         size_t                                  inlen, outlen;\r
402         WV_PROTECTION_DOMAIN    *pd;\r
403         WV_MEMORY_WINDOW                *mw;\r
404         NTSTATUS                                status;\r
405         ib_api_status_t                 ib_status;\r
406         ci_umv_buf_t                    verbsData;\r
407 \r
408         status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_ID), &inid, &inlen);\r
409         if (!NT_SUCCESS(status)) {\r
410                 goto err1;\r
411         }\r
412         status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_ID), &outid, &outlen);\r
413         if (!NT_SUCCESS(status)) {\r
414                 goto err1;\r
415         }\r
416 \r
417         pd = WvPdAcquire(pProvider, inid->Id);\r
418         if (pd == NULL) {\r
419                 status = STATUS_NOT_FOUND;\r
420                 goto err1;\r
421         }\r
422 \r
423         mw = ExAllocatePoolWithTag(PagedPool, sizeof(WV_MEMORY_WINDOW), 'wmvw');\r
424         if (mw == NULL) {\r
425                 status = STATUS_NO_MEMORY;\r
426                 goto err2;\r
427         }\r
428 \r
429         WvInitVerbsData(&verbsData, inid->VerbInfo, inlen - sizeof(WV_IO_ID),\r
430                                         outlen - sizeof(WV_IO_ID), inid + 1);\r
431         ib_status = pd->pVerbs->create_mw(pd->hVerbsPd, &outid->Data, &mw->hVerbsMw,\r
432                                                                           &verbsData);\r
433         if (ib_status != IB_SUCCESS) {\r
434                 status = STATUS_UNSUCCESSFUL;\r
435                 goto err3;\r
436         }\r
437 \r
438         KeAcquireGuardedMutex(&pProvider->Lock);\r
439         outid->Id = IndexListInsertHead(&pProvider->MwIndex, mw);\r
440         if (outid->Id == 0) {\r
441                 status = STATUS_NO_MEMORY;\r
442                 goto err3;\r
443         }\r
444         InsertHeadList(&pd->MwList, &mw->Entry);\r
445         KeReleaseGuardedMutex(&pProvider->Lock);\r
446 \r
447         mw->pPd = pd;\r
448 \r
449         WvProviderEnableRemove(pProvider);\r
450         outid->VerbInfo = verbsData.status;\r
451         WdfRequestCompleteWithInformation(Request, status, outlen);\r
452         return;\r
453 \r
454 err3:\r
455         KeReleaseGuardedMutex(&pProvider->Lock);\r
456         WvMwFree(mw);\r
457 err2:\r
458         WvPdRelease(pd);\r
459 err1:\r
460         WdfRequestComplete(Request, status);\r
461 }\r
462 \r
463 void WvMwDeallocate(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
464 {\r
465         WV_MEMORY_WINDOW        *mw;\r
466         UINT64                          *id;\r
467         NTSTATUS                        status;\r
468 \r
469         status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
470         if (!NT_SUCCESS(status)) {\r
471                 goto out;\r
472         }\r
473 \r
474         KeAcquireGuardedMutex(&pProvider->Lock);\r
475         WvProviderDisableRemove(pProvider);\r
476         mw = IndexListAt(&pProvider->MwIndex, (SIZE_T) *id);\r
477         if (mw == NULL) {\r
478                 status = STATUS_NOT_FOUND;\r
479         } else {\r
480                 IndexListRemove(&pProvider->MwIndex, (SIZE_T) *id);\r
481                 RemoveEntryList(&mw->Entry);\r
482                 status = STATUS_SUCCESS;\r
483         }\r
484         KeReleaseGuardedMutex(&pProvider->Lock);\r
485 \r
486         if (NT_SUCCESS(status)) {\r
487                 WvMwFree(mw);\r
488         }\r
489         WvProviderEnableRemove(pProvider);\r
490 out:\r
491         WdfRequestComplete(Request, status);\r
492 }\r
493 \r
494 void WvMwFree(WV_MEMORY_WINDOW *pMw)\r
495 {\r
496         if (pMw->hVerbsMw != NULL) {\r
497                 pMw->pPd->pVerbs->destroy_mw(pMw->hVerbsMw);\r
498         }\r
499 \r
500         WvPdPut(pMw->pPd);\r
501         ExFreePool(pMw);\r
502 }\r
503 \r
504 static void WvVerbsConvertAv(ib_av_attr_t *pVerbsAv, WV_IO_AV *pAv)\r
505 {\r
506         pVerbsAv->grh_valid = pAv->NetworkRouteValid;\r
507         if (pVerbsAv->grh_valid) {\r
508                 pVerbsAv->grh.ver_class_flow =\r
509                         RtlUlongByteSwap(RtlUlongByteSwap(pAv->FlowLabel) | (pAv->TrafficClass << 20));\r
510                 pVerbsAv->grh.hop_limit = pAv->HopLimit;\r
511                 RtlCopyMemory(&pVerbsAv->grh.src_gid, pAv->SGid, sizeof(pAv->SGid));\r
512                 RtlCopyMemory(&pVerbsAv->grh.dest_gid, pAv->DGid, sizeof(pAv->DGid));\r
513         }\r
514 \r
515         pVerbsAv->port_num = pAv->PortNumber;\r
516         pVerbsAv->sl = pAv->ServiceLevel;\r
517         pVerbsAv->dlid = pAv->DLid;\r
518         pVerbsAv->static_rate = pAv->StaticRate;\r
519         pVerbsAv->path_bits = pAv->SourcePathBits;\r
520 }\r
521 \r
522 void WvAhCreate(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
523 {\r
524         size_t                                  inlen, outlen;\r
525         WV_PROTECTION_DOMAIN    *pd;\r
526         WV_ADDRESS_HANDLE               *ah;\r
527         WV_IO_AH_CREATE                 *pinAv, *poutAv;\r
528         ib_av_attr_t                    av;\r
529         NTSTATUS                                status;\r
530         ib_api_status_t                 ib_status;\r
531         ci_umv_buf_t                    verbsData;\r
532 \r
533         status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_AH_CREATE),\r
534                                                                                    &pinAv, &inlen);\r
535         if (!NT_SUCCESS(status)) {\r
536                 goto err1;\r
537         }\r
538         status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_AH_CREATE),\r
539                                                                                         &poutAv, &outlen);\r
540         if (!NT_SUCCESS(status)) {\r
541                 goto err1;\r
542         }\r
543 \r
544         pd = WvPdAcquire(pProvider, pinAv->Id.Id);\r
545         if (pd == NULL) {\r
546                 status = STATUS_NOT_FOUND;\r
547                 goto err1;\r
548         }\r
549 \r
550         ah = ExAllocatePoolWithTag(PagedPool, sizeof(WV_ADDRESS_HANDLE), 'havw');\r
551         if (ah == NULL) {\r
552                 status = STATUS_NO_MEMORY;\r
553                 goto err2;\r
554         }\r
555 \r
556         WvVerbsConvertAv(&av, &pinAv->AddressVector);\r
557         WvInitVerbsData(&verbsData, pinAv->Id.VerbInfo, inlen - sizeof(WV_IO_AH_CREATE),\r
558                                         outlen - sizeof(WV_IO_AH_CREATE), pinAv + 1);\r
559         ib_status = pd->pVerbs->create_av(pd->hVerbsPd, &av, &ah->hVerbsAh, &verbsData);\r
560         if (ib_status != IB_SUCCESS) {\r
561                 status = STATUS_UNSUCCESSFUL;\r
562                 goto err3;\r
563         }\r
564 \r
565         KeAcquireGuardedMutex(&pProvider->Lock);\r
566         poutAv->Id.Id = IndexListInsertHead(&pProvider->AhIndex, ah);\r
567         if (poutAv->Id.Id == 0) {\r
568                 status = STATUS_NO_MEMORY;\r
569                 goto err3;\r
570         }\r
571         InsertHeadList(&pd->AhList, &ah->Entry);\r
572         KeReleaseGuardedMutex(&pProvider->Lock);\r
573 \r
574         ah->pPd = pd;\r
575 \r
576         WvProviderEnableRemove(pProvider);\r
577         poutAv->Id.VerbInfo = verbsData.status;\r
578         WdfRequestCompleteWithInformation(Request, status, outlen);\r
579         return;\r
580 \r
581 err3:\r
582         KeReleaseGuardedMutex(&pProvider->Lock);\r
583         WvAhFree(ah);\r
584 err2:\r
585         WvPdRelease(pd);\r
586 err1:\r
587         WdfRequestComplete(Request, status);\r
588 }\r
589 \r
590 void WvAhDestroy(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
591 {\r
592         WV_ADDRESS_HANDLE       *ah;\r
593         UINT64                          *id;\r
594         NTSTATUS                        status;\r
595 \r
596         status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
597         if (!NT_SUCCESS(status)) {\r
598                 goto out;\r
599         }\r
600 \r
601         KeAcquireGuardedMutex(&pProvider->Lock);\r
602         WvProviderDisableRemove(pProvider);\r
603         ah = IndexListAt(&pProvider->AhIndex, (SIZE_T) *id);\r
604         if (ah == NULL) {\r
605                 status = STATUS_NOT_FOUND;\r
606         } else {\r
607                 IndexListRemove(&pProvider->AhIndex, (SIZE_T) *id);\r
608                 RemoveEntryList(&ah->Entry);\r
609                 status = STATUS_SUCCESS;\r
610         }\r
611         KeReleaseGuardedMutex(&pProvider->Lock);\r
612 \r
613         if (NT_SUCCESS(status)) {\r
614                 WvAhFree(ah);\r
615         }\r
616         WvProviderEnableRemove(pProvider);\r
617 out:\r
618         WdfRequestComplete(Request, status);\r
619 }\r
620 \r
621 void WvAhFree(WV_ADDRESS_HANDLE *pAh)\r
622 {\r
623         if (pAh->hVerbsAh != NULL) {\r
624                 pAh->pPd->pVerbs->destroy_av(pAh->hVerbsAh);\r
625         }\r
626 \r
627         WvPdPut(pAh->pPd);\r
628         ExFreePool(pAh);\r
629 }\r