[IBBUS] __iou/port_was_hibernated() change NTSTATUS --> ib_api_status_t to be consist...
[mirror/winof/.git] / core / winmad / kernel / wm_reg.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 <iba\ib_al.h>\r
31 #include "wm_driver.h"\r
32 #include "wm_reg.h"\r
33 #include "wm_ioctl.h"\r
34 \r
35 WM_REGISTRATION *WmRegAcquire(WM_PROVIDER *pProvider, UINT64 Id)\r
36 {\r
37         WM_REGISTRATION *reg;\r
38 \r
39         KeAcquireGuardedMutex(&pProvider->Lock);\r
40         WmProviderDisableRemove(pProvider);\r
41         reg = IndexListAt(&pProvider->RegIndex, (SIZE_T) Id);\r
42         if (reg != NULL && reg->pDevice != NULL) {\r
43                 InterlockedIncrement(&reg->Ref);\r
44         } else {\r
45                 reg = NULL;\r
46                 WmProviderEnableRemove(pProvider);\r
47         }\r
48         KeReleaseGuardedMutex(&pProvider->Lock);\r
49         return reg;\r
50 }\r
51 \r
52 void WmRegRelease(WM_REGISTRATION *pRegistration)\r
53 {\r
54         WmProviderEnableRemove(pRegistration->pProvider);\r
55         InterlockedDecrement(&pRegistration->Ref);\r
56 }\r
57 \r
58 static WM_REGISTRATION *WmRegAlloc(WM_PROVIDER *pProvider)\r
59 {\r
60         WM_REGISTRATION *reg;\r
61 \r
62         reg = ExAllocatePoolWithTag(PagedPool, sizeof(WM_REGISTRATION), 'grmw');\r
63         if (reg == NULL) {\r
64                 return NULL;\r
65         }\r
66 \r
67         RtlZeroMemory(reg, sizeof(WM_REGISTRATION));\r
68         reg->Ref = 1;\r
69 \r
70         reg->pProvider = pProvider;\r
71         WmProviderGet(pProvider);\r
72         return reg;\r
73 }\r
74 \r
75 static int WmConvertMethods(ib_mad_svc_t *svc, WM_IO_REGISTER *pAttributes)\r
76 {\r
77         int i, j, unsolicited = 0;\r
78 \r
79         for (i = 0; i < 16; i++) {\r
80                 for (j = 0; j < 8; j++) {\r
81                         if (((pAttributes->Methods[i] >> j) & 0x01) != 0) {\r
82                                 svc->method_array[i * 8 + j] = 1;\r
83                                 unsolicited = 1;\r
84                         }\r
85                 }\r
86         }\r
87         return unsolicited;\r
88 }\r
89 \r
90 static NTSTATUS WmRegInit(WM_REGISTRATION *pRegistration, WM_IO_REGISTER *pAttributes)\r
91 {\r
92         WM_IB_DEVICE    *dev;\r
93         ib_qp_create_t  attr;\r
94         ib_mad_svc_t    svc;\r
95         ib_api_status_t ib_status;\r
96         NTSTATUS                status;\r
97 \r
98         RtlZeroMemory(&attr, sizeof attr);\r
99         if (pAttributes->Qpn == 0) {\r
100                 attr.qp_type = IB_QPT_QP0_ALIAS;\r
101         } else if (pAttributes->Qpn == IB_QP1) {\r
102                 attr.qp_type = IB_QPT_QP1_ALIAS;\r
103         } else {\r
104                 return STATUS_BAD_NETWORK_PATH;\r
105         }\r
106 \r
107         dev = WmIbDeviceGet(pAttributes->Guid);\r
108         if (dev == NULL) {\r
109                 return STATUS_NO_SUCH_DEVICE;\r
110         }\r
111 \r
112         if (--pAttributes->Port > dev->PortCount) {\r
113                 status = STATUS_INVALID_PORT_HANDLE;\r
114                 goto err1;\r
115         }\r
116 \r
117         ib_status = dev->IbInterface.open_al(&pRegistration->hIbal);\r
118         if (ib_status != IB_SUCCESS) {\r
119                 status = STATUS_UNSUCCESSFUL;\r
120                 goto err1;\r
121         }\r
122 \r
123         ib_status = dev->IbInterface.open_ca(pRegistration->hIbal, pAttributes->Guid,\r
124                                                                                  NULL, NULL, &pRegistration->hCa);\r
125         if (ib_status != IB_SUCCESS) {\r
126                 goto err2;\r
127         }\r
128 \r
129         ib_status = dev->IbInterface.alloc_pd(pRegistration->hCa, IB_PDT_ALIAS,\r
130                                                                                   NULL, &pRegistration->hPd);\r
131         if (ib_status != IB_SUCCESS) {\r
132                 goto err3;\r
133         }\r
134 \r
135         attr.sq_depth = attr.rq_depth = 1;\r
136         attr.sq_sge = attr.rq_sge = 1;\r
137         attr.sq_signaled = 1;\r
138 \r
139         ib_status = dev->IbInterface.get_spl_qp(pRegistration->hPd,\r
140                                                                                         dev->pPortArray[pAttributes->Port].Guid,\r
141                                                                                         &attr, pRegistration, NULL,\r
142                                                                                         &pRegistration->hMadPool,\r
143                                                                                         &pRegistration->hQp);\r
144         if (ib_status != IB_SUCCESS) {\r
145                 status = STATUS_UNSUCCESSFUL;\r
146                 goto err4;\r
147         }\r
148 \r
149         svc.mad_svc_context = pRegistration->pProvider;\r
150         svc.pfn_mad_send_cb = WmSendHandler;\r
151         svc.pfn_mad_recv_cb = WmReceiveHandler;\r
152         svc.support_unsol = WmConvertMethods(&svc, pAttributes);\r
153         svc.mgmt_class = pAttributes->Class;\r
154         svc.mgmt_version = pAttributes->Version;\r
155     svc.svc_type = IB_MAD_SVC_DEFAULT;\r
156 \r
157         ib_status = dev->IbInterface.reg_mad_svc(pRegistration->hQp, &svc,\r
158                                                                                          &pRegistration->hService);\r
159         if (ib_status != IB_SUCCESS) {\r
160                 status = STATUS_UNSUCCESSFUL;\r
161                 goto err5;\r
162         }\r
163 \r
164         pRegistration->pDevice = dev;\r
165         return STATUS_SUCCESS;\r
166 \r
167 err5:\r
168         dev->IbInterface.destroy_qp(pRegistration->hQp, NULL);\r
169 err4:\r
170         dev->IbInterface.dealloc_pd(pRegistration->hPd, NULL);\r
171 err3:\r
172         dev->IbInterface.close_ca(pRegistration->hCa, NULL);\r
173 err2:\r
174         dev->IbInterface.close_al(pRegistration->hIbal);\r
175 err1:\r
176         WmIbDevicePut(dev);\r
177         pRegistration->pDevice = NULL;\r
178         return status;\r
179 }\r
180 \r
181 void WmRegister(WM_PROVIDER *pProvider, WDFREQUEST Request)\r
182 {\r
183         WM_REGISTRATION *reg;\r
184         WM_IO_REGISTER  *attr;\r
185         UINT64                  *id;\r
186         NTSTATUS                status;\r
187 \r
188         status = WdfRequestRetrieveInputBuffer(Request, sizeof(WM_IO_REGISTER), &attr, NULL);\r
189         if (!NT_SUCCESS(status)) {\r
190                 goto err1;\r
191         }\r
192         status = WdfRequestRetrieveOutputBuffer(Request, sizeof(UINT64), &id, NULL);\r
193         if (!NT_SUCCESS(status)) {\r
194                 goto err1;\r
195         }\r
196 \r
197         reg = WmRegAlloc(pProvider);\r
198         if (reg == NULL) {\r
199                 status = STATUS_NO_MEMORY;\r
200                 goto err1;\r
201         }\r
202 \r
203         KeAcquireGuardedMutex(&pProvider->Lock);\r
204         WmProviderDisableRemove(pProvider);\r
205         KeReleaseGuardedMutex(&pProvider->Lock);\r
206 \r
207         status = WmRegInit(reg, attr);\r
208         if (!NT_SUCCESS(status)) {\r
209                 goto err2;\r
210         }\r
211 \r
212         KeAcquireGuardedMutex(&pProvider->Lock);\r
213         reg->Id = IndexListInsertHead(&pProvider->RegIndex, reg);\r
214         if (reg->Id == 0) {\r
215                 status = STATUS_NO_MEMORY;\r
216                 goto err2;\r
217         }\r
218         KeReleaseGuardedMutex(&pProvider->Lock);\r
219 \r
220         WmProviderEnableRemove(pProvider);\r
221         *id = reg->Id;\r
222         WdfRequestCompleteWithInformation(Request, status, sizeof(UINT64));\r
223         return;\r
224 \r
225 err2:\r
226         WmRegFree(reg);\r
227         WmProviderEnableRemove(pProvider);\r
228 err1:\r
229         WdfRequestComplete(Request, status);\r
230 }\r
231 \r
232 void WmDeregister(WM_PROVIDER *pProvider, WDFREQUEST Request)\r
233 {\r
234         WM_REGISTRATION *reg;\r
235         UINT64                  *id;\r
236         NTSTATUS                status;\r
237 \r
238         status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
239         if (!NT_SUCCESS(status)) {\r
240                 goto out;\r
241         }\r
242 \r
243         KeAcquireGuardedMutex(&pProvider->Lock);\r
244         WmProviderDisableRemove(pProvider);\r
245         reg = IndexListAt(&pProvider->RegIndex, (SIZE_T) *id);\r
246         if (reg == NULL) {\r
247                 status = STATUS_NO_SUCH_DEVICE;\r
248         } else if (reg->Ref > 1) {\r
249                 status = STATUS_ACCESS_DENIED;\r
250         } else {\r
251                 IndexListRemove(&pProvider->RegIndex, (SIZE_T) *id);\r
252                 status = STATUS_SUCCESS;\r
253         }\r
254         KeReleaseGuardedMutex(&pProvider->Lock);\r
255 \r
256         if (NT_SUCCESS(status)) {\r
257                 WmRegFree(reg);\r
258         }\r
259         WmProviderEnableRemove(pProvider);\r
260 out:\r
261         WdfRequestComplete(Request, status);\r
262 }\r
263 \r
264 void WmRegFree(WM_REGISTRATION *pRegistatration)\r
265 {\r
266         WmRegRemoveHandler(pRegistatration);\r
267         WmProviderPut(pRegistatration->pProvider);\r
268         ExFreePool(pRegistatration);\r
269 }\r
270 \r
271 void WmRegRemoveHandler(WM_REGISTRATION *pRegistration)\r
272 {\r
273         if (pRegistration->pDevice == NULL) {\r
274                 return;\r
275         }\r
276 \r
277         pRegistration->pDevice->IbInterface.destroy_qp(pRegistration->hQp, NULL);\r
278         pRegistration->pDevice->IbInterface.dealloc_pd(pRegistration->hPd, NULL);\r
279         pRegistration->pDevice->IbInterface.close_ca(pRegistration->hCa, NULL);\r
280         pRegistration->pDevice->IbInterface.close_al(pRegistration->hIbal);\r
281 \r
282         WmProviderFlushReceives(pRegistration->pProvider, pRegistration);\r
283         WmIbDevicePut(pRegistration->pDevice);\r
284         pRegistration->pDevice = NULL;\r
285 }\r