[opensm] removed opensm\user\include\ib_types.h, even though it was not used, it...
[mirror/winof/.git] / core / winverbs / kernel / wv_srq.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_driver.h"\r
31 #include "wv_srq.h"\r
32 #include "wv_ioctl.h"\r
33 \r
34 void WvSrqGet(WV_SHARED_RECEIVE_QUEUE *pSrq)\r
35 {\r
36         InterlockedIncrement(&pSrq->Ref);\r
37 }\r
38 \r
39 void WvSrqPut(WV_SHARED_RECEIVE_QUEUE *pSrq)\r
40 {\r
41         if (InterlockedDecrement(&pSrq->Ref) == 0) {\r
42                 KeSetEvent(&pSrq->Event, 0, FALSE);\r
43         }\r
44 }\r
45 \r
46 WV_SHARED_RECEIVE_QUEUE *WvSrqAcquire(WV_PROVIDER *pProvider, UINT64 Id)\r
47 {\r
48         WV_SHARED_RECEIVE_QUEUE *srq;\r
49 \r
50         KeAcquireGuardedMutex(&pProvider->Lock);\r
51         WvProviderDisableRemove(pProvider);\r
52         srq = IndexListAt(&pProvider->SrqIndex, (SIZE_T) Id);\r
53         if (srq != NULL && srq->hVerbsSrq != NULL) {\r
54                 WvSrqGet(srq);\r
55         } else {\r
56                 srq = NULL;\r
57                 WvProviderEnableRemove(pProvider);\r
58         }\r
59         KeReleaseGuardedMutex(&pProvider->Lock);\r
60 \r
61         return srq;\r
62 }\r
63 \r
64 void WvSrqRelease(WV_SHARED_RECEIVE_QUEUE *pSrq)\r
65 {\r
66         WvProviderEnableRemove(pSrq->pProvider);\r
67         WvSrqPut(pSrq);\r
68 }\r
69 \r
70 static void WvVerbsConvertSrq(ib_srq_attr_t *pVerbsAttr,\r
71                                                           WV_IO_SRQ_ATTRIBUTES *pAttr)\r
72 {\r
73         pVerbsAttr->max_wr        = pAttr->MaxWr;\r
74         pVerbsAttr->max_sge       = pAttr->MaxSge;\r
75         pVerbsAttr->srq_limit = pAttr->SrqLimit;\r
76 }\r
77 \r
78 static void WvSrqEventHandler(ib_event_rec_t *pEvent)\r
79 {\r
80         WV_SHARED_RECEIVE_QUEUE *srq = pEvent->context;\r
81 \r
82         switch (pEvent->type) {\r
83         case IB_AE_SRQ_LIMIT_REACHED:\r
84                 WvFlushQueue(srq->Queue, STATUS_ALERTED);\r
85                 break;\r
86         case IB_AE_SRQ_QP_LAST_WQE_REACHED:\r
87                 WvFlushQueue(srq->Queue, STATUS_NOTIFY_CLEANUP);\r
88                 break;\r
89         default:\r
90                 WvFlushQueue(srq->Queue, STATUS_UNEXPECTED_IO_ERROR);\r
91                 break;\r
92         }\r
93 }\r
94 \r
95 static NTSTATUS WvSrqAlloc(WV_PROTECTION_DOMAIN *pPd, WV_IO_SRQ_ATTRIBUTES *pAttr,\r
96                                                   WV_SHARED_RECEIVE_QUEUE **ppSrq, ci_umv_buf_t *pVerbsData)\r
97 {\r
98         WV_SHARED_RECEIVE_QUEUE *srq;\r
99         ib_srq_attr_t                   attr;\r
100         ib_api_status_t                 ib_status;\r
101         NTSTATUS                                status;\r
102         WDF_IO_QUEUE_CONFIG             config;\r
103 \r
104         srq = ExAllocatePoolWithTag(NonPagedPool, sizeof(WV_SHARED_RECEIVE_QUEUE), 'rsvw');\r
105         if (srq == NULL) {\r
106                 return STATUS_NO_MEMORY;\r
107         }\r
108 \r
109         srq->Ref = 1;\r
110         KeInitializeEvent(&srq->Event, NotificationEvent, FALSE);\r
111 \r
112         WDF_IO_QUEUE_CONFIG_INIT(&config, WdfIoQueueDispatchManual);\r
113         status = WdfIoQueueCreate(ControlDevice, &config,\r
114                                                           WDF_NO_OBJECT_ATTRIBUTES, &srq->Queue);\r
115         if (!NT_SUCCESS(status)) {\r
116                 goto err1;\r
117         }\r
118 \r
119         WvVerbsConvertSrq(&attr, pAttr);\r
120         ib_status = pPd->pVerbs->create_srq(pPd->hVerbsPd, srq, WvSrqEventHandler,\r
121                                                                                 &attr, &srq->hVerbsSrq, pVerbsData);\r
122         if (ib_status != IB_SUCCESS) {\r
123                 goto err2;\r
124         }\r
125 \r
126         WvPdGet(pPd);\r
127         srq->pPd = pPd;\r
128         srq->pProvider = pPd->pDevice->pProvider;\r
129         srq->pVerbs = pPd->pVerbs;\r
130         *ppSrq = srq;\r
131         return STATUS_SUCCESS;\r
132 \r
133 err2:\r
134         WdfObjectDelete(srq->Queue);\r
135 err1:\r
136         ExFreePoolWithTag(srq, 'rsvw');\r
137         return STATUS_UNSUCCESSFUL;\r
138 }\r
139 \r
140 void WvSrqCreate(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
141 {\r
142         WV_IO_SRQ_ATTRIBUTES    *inAttr, *outAttr;\r
143         size_t                                  inlen, outlen;\r
144         WV_PROTECTION_DOMAIN    *pd;\r
145         WV_SHARED_RECEIVE_QUEUE *srq;\r
146         NTSTATUS                                status;\r
147         ci_umv_buf_t                    verbsData;\r
148 \r
149         status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_SRQ_ATTRIBUTES),\r
150                                                                                    &inAttr, &inlen);\r
151         if (!NT_SUCCESS(status)) {\r
152                 goto err1;\r
153         }\r
154         status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_SRQ_ATTRIBUTES),\r
155                                                                                         &outAttr, &outlen);\r
156         if (!NT_SUCCESS(status)) {\r
157                 goto err1;\r
158         }\r
159 \r
160         pd = WvPdAcquire(pProvider, inAttr->Id.Id);\r
161         if (pd == NULL) {\r
162                 status = STATUS_NOT_FOUND;\r
163                 goto err1;\r
164         }\r
165 \r
166         WvInitVerbsData(&verbsData, inAttr->Id.VerbInfo, inlen - sizeof(WV_IO_SRQ_ATTRIBUTES),\r
167                                         outlen - sizeof(WV_IO_SRQ_ATTRIBUTES), inAttr + 1);\r
168         status = WvSrqAlloc(pd, inAttr, &srq, &verbsData);\r
169         if (!NT_SUCCESS(status)) {\r
170                 goto err2;\r
171         }\r
172 \r
173         KeAcquireGuardedMutex(&pProvider->Lock);\r
174         outAttr->Id.Id = IndexListInsertHead(&pProvider->SrqIndex, srq);\r
175         if (outAttr->Id.Id == 0) {\r
176                 status = STATUS_NO_MEMORY;\r
177                 goto err3;\r
178         }\r
179         InsertHeadList(&pd->SrqList, &srq->Entry);\r
180         KeReleaseGuardedMutex(&pProvider->Lock);\r
181 \r
182         WvPdRelease(pd);\r
183         outAttr->Id.VerbInfo = verbsData.status;\r
184         WdfRequestCompleteWithInformation(Request, status, outlen);\r
185         return;\r
186 \r
187 err3:\r
188         KeReleaseGuardedMutex(&pProvider->Lock);\r
189         WvSrqFree(srq);\r
190 err2:\r
191         WvPdRelease(pd);\r
192 err1:\r
193         WdfRequestComplete(Request, status);\r
194 }\r
195 \r
196 void WvSrqDestroy(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
197 {\r
198         WV_SHARED_RECEIVE_QUEUE *srq;\r
199         UINT64                                  *id;\r
200         NTSTATUS                                status;\r
201 \r
202         status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
203         if (!NT_SUCCESS(status)) {\r
204                 goto out;\r
205         }\r
206 \r
207         KeAcquireGuardedMutex(&pProvider->Lock);\r
208         WvProviderDisableRemove(pProvider);\r
209         srq = IndexListAt(&pProvider->SrqIndex, (SIZE_T) *id);\r
210         if (srq == NULL) {\r
211                 status = STATUS_NOT_FOUND;\r
212         } else if (srq->Ref > 1) {\r
213                 status = STATUS_ACCESS_DENIED;\r
214         } else {\r
215                 IndexListRemove(&pProvider->SrqIndex, (SIZE_T) *id);\r
216                 RemoveEntryList(&srq->Entry);\r
217                 status = STATUS_SUCCESS;\r
218         }\r
219         KeReleaseGuardedMutex(&pProvider->Lock);\r
220 \r
221         if (NT_SUCCESS(status)) {\r
222                 WvSrqFree(srq);\r
223         }\r
224         WvProviderEnableRemove(pProvider);\r
225 out:\r
226         WdfRequestComplete(Request, status);\r
227 }\r
228 \r
229 void WvSrqFree(WV_SHARED_RECEIVE_QUEUE *pSrq)\r
230 {\r
231         if (InterlockedDecrement(&pSrq->Ref) > 0) {\r
232                 KeWaitForSingleObject(&pSrq->Event, Executive, KernelMode, FALSE, NULL);\r
233         }\r
234 \r
235         if (pSrq->hVerbsSrq != NULL) {\r
236                 pSrq->pVerbs->destroy_srq(pSrq->hVerbsSrq);\r
237         }\r
238 \r
239         WdfIoQueuePurgeSynchronously(pSrq->Queue);\r
240         WdfObjectDelete(pSrq->Queue);\r
241         WvPdPut(pSrq->pPd);\r
242         ExFreePoolWithTag(pSrq, 'rsvw');\r
243 }\r
244 \r
245 void WvSrqModify(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
246 {\r
247         WV_IO_SRQ_ATTRIBUTES    *pinAttr, *poutAttr;\r
248         size_t                                  inlen, outlen, len = 0;\r
249         WV_SHARED_RECEIVE_QUEUE *srq;\r
250         ib_srq_attr_t                   attr;\r
251         NTSTATUS                                status;\r
252         ib_api_status_t                 ib_status;\r
253         ci_umv_buf_t                    verbsData;\r
254 \r
255         status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_SRQ_ATTRIBUTES),\r
256                                                                                    &pinAttr, &inlen);\r
257         if (!NT_SUCCESS(status)) {\r
258                 goto complete;\r
259         }\r
260         status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_SRQ_ATTRIBUTES),\r
261                                                                                         &poutAttr, &outlen);\r
262         if (!NT_SUCCESS(status)) {\r
263                 goto complete;\r
264         }\r
265 \r
266         srq = WvSrqAcquire(pProvider, pinAttr->Id.Id);\r
267         if (srq == NULL) {\r
268                 status = STATUS_NOT_FOUND;\r
269                 goto complete;\r
270         }\r
271 \r
272         WvInitVerbsData(&verbsData, pinAttr->Id.VerbInfo, inlen - sizeof(WV_IO_SRQ_ATTRIBUTES),\r
273                                         outlen - sizeof(WV_IO_SRQ_ATTRIBUTES), pinAttr + 1);\r
274         WvVerbsConvertSrq(&attr, pinAttr);\r
275         ib_status = srq->pVerbs->modify_srq(srq->hVerbsSrq, &attr,\r
276                                                                                 IB_SRQ_MAX_WR | IB_SRQ_LIMIT, &verbsData);\r
277         WvSrqRelease(srq);\r
278 \r
279         if (ib_status != IB_SUCCESS) {\r
280                 status = STATUS_UNSUCCESSFUL;\r
281         }\r
282 \r
283         len = outlen;\r
284         poutAttr->Id.VerbInfo = verbsData.status;\r
285 complete:\r
286         WdfRequestCompleteWithInformation(Request, status, len);\r
287 }\r
288 \r
289 void WvSrqQuery(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
290 {\r
291         WV_IO_SRQ_ATTRIBUTES    *pinAttr, *poutAttr;\r
292         size_t                                  inlen, outlen, len = 0;\r
293         WV_SHARED_RECEIVE_QUEUE *srq;\r
294         ib_srq_attr_t                   attr;\r
295         NTSTATUS                                status;\r
296         ci_umv_buf_t                    verbsData;\r
297 \r
298         status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_SRQ_ATTRIBUTES),\r
299                                                                                    &pinAttr, &inlen);\r
300         if (!NT_SUCCESS(status)) {\r
301                 goto complete;\r
302         }\r
303         status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_SRQ_ATTRIBUTES),\r
304                                                                                         &poutAttr, &outlen);\r
305         if (!NT_SUCCESS(status)) {\r
306                 goto complete;\r
307         }\r
308 \r
309         srq = WvSrqAcquire(pProvider, pinAttr->Id.Id);\r
310         if (srq == NULL) {\r
311                 status = STATUS_NOT_FOUND;\r
312                 goto complete;\r
313         }\r
314 \r
315         WvInitVerbsData(&verbsData, pinAttr->Id.VerbInfo, inlen - sizeof(WV_IO_SRQ_ATTRIBUTES),\r
316                                         outlen - sizeof(WV_IO_SRQ_ATTRIBUTES), pinAttr + 1);\r
317         srq->pVerbs->query_srq(srq->hVerbsSrq, &attr, &verbsData);\r
318         WvSrqRelease(srq);\r
319 \r
320         poutAttr->Id.VerbInfo = verbsData.status;\r
321         poutAttr->MaxWr = attr.max_wr;\r
322         poutAttr->MaxSge = attr.max_sge;\r
323         poutAttr->SrqLimit = attr.srq_limit;\r
324         len = outlen;\r
325 complete:\r
326         WdfRequestCompleteWithInformation(Request, status, len);\r
327 }\r
328 \r
329 void WvSrqNotify(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
330 {\r
331         UINT64                                  *id;\r
332         WV_SHARED_RECEIVE_QUEUE *srq;\r
333         NTSTATUS                                status;\r
334 \r
335         status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
336         if (!NT_SUCCESS(status)) {\r
337                 goto out;\r
338         }\r
339 \r
340         srq = WvSrqAcquire(pProvider, *id);\r
341         if (srq == NULL) {\r
342                 status = STATUS_NOT_FOUND;\r
343                 goto out;\r
344         }\r
345 \r
346         WdfObjectAcquireLock(srq->Queue);\r
347         status = WdfRequestForwardToIoQueue(Request, srq->Queue);\r
348         WdfObjectReleaseLock(srq->Queue);\r
349         WvSrqRelease(srq);\r
350 \r
351 out:\r
352         if (!NT_SUCCESS(status)) {\r
353                 WdfRequestComplete(Request, status);\r
354         }\r
355 }\r
356 \r
357 void WvSrqCancel(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
358 {\r
359         UINT64                                  *id;\r
360         WV_SHARED_RECEIVE_QUEUE *srq;\r
361         NTSTATUS                                status;\r
362 \r
363         status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
364         if (!NT_SUCCESS(status)) {\r
365                 goto out;\r
366         }\r
367 \r
368         srq = WvSrqAcquire(pProvider, *id);\r
369         if (srq == NULL) {\r
370                 status = STATUS_NOT_FOUND;\r
371                 goto out;\r
372         }\r
373 \r
374         WvFlushQueue(srq->Queue, STATUS_CANCELLED);\r
375         WvSrqRelease(srq);\r
376 \r
377 out:\r
378         WdfRequestComplete(Request, status);\r
379 }\r