winverbs: make PD derive from IWVOverlapped
[mirror/winof/.git] / core / winverbs / user / wv_pd.cpp
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_base.h"\r
31 #include "wv_memory.h"\r
32 #include "wv_pd.h"\r
33 #include "wv_srq.h"\r
34 #include "wv_qp.h"\r
35 #include "wv_ioctl.h"\r
36 \r
37 CWVProtectionDomain::CWVProtectionDomain(CWVDevice *pDevice)\r
38 {\r
39         pDevice->AddRef();\r
40         m_pDevice = pDevice;\r
41         m_pVerbs = &pDevice->m_Verbs;\r
42         m_hFile = pDevice->m_hFile;\r
43         m_hVerbsPd = NULL;\r
44 }\r
45 \r
46 STDMETHODIMP CWVProtectionDomain::\r
47 Allocate(void)\r
48 {\r
49         WV_IO_ID                *pId;\r
50         DWORD                   bytes;\r
51         ib_api_status_t stat;\r
52         HRESULT                 hr;\r
53         ci_umv_buf_t    verbsData;\r
54         CWVBuffer               buf;\r
55 \r
56         stat = m_pVerbs->pre_allocate_pd(m_pDevice->m_hVerbsDevice, &verbsData,\r
57                                                                          &m_hVerbsPd);\r
58         if (stat != IB_SUCCESS) {\r
59                 return WvConvertIbStatus(stat);\r
60         }\r
61 \r
62         bytes = sizeof WV_IO_ID + max(verbsData.input_size, verbsData.output_size);\r
63         pId = (WV_IO_ID *) buf.Get(bytes);\r
64         if (pId == NULL) {\r
65                 hr = WV_NO_MEMORY;\r
66                 goto post;\r
67         }\r
68 \r
69         pId->Id = m_pDevice->m_Id;\r
70         pId->VerbInfo = verbsData.command;\r
71         RtlCopyMemory(pId + 1, (void *) (ULONG_PTR) verbsData.p_inout_buf,\r
72                                   verbsData.input_size);\r
73 \r
74         if (WvDeviceIoControl(m_hFile, WV_IOCTL_PD_ALLOCATE,\r
75                                                   pId, sizeof WV_IO_ID + verbsData.input_size,\r
76                                                   pId, sizeof WV_IO_ID + verbsData.output_size,\r
77                                                   &bytes, NULL)) {\r
78                 hr = WV_SUCCESS;\r
79                 m_Id = pId->Id;\r
80         } else {\r
81                 hr = HRESULT_FROM_WIN32(GetLastError());\r
82         }\r
83 \r
84         verbsData.status = pId->VerbInfo;\r
85         RtlCopyMemory((void *) (ULONG_PTR) verbsData.p_inout_buf, pId + 1,\r
86                                   verbsData.output_size);\r
87         buf.Put();\r
88 \r
89 post:\r
90         m_pVerbs->post_allocate_pd(m_pDevice->m_hVerbsDevice, (ib_api_status_t) hr,\r
91                                                            &m_hVerbsPd, &verbsData);\r
92         return hr;\r
93 }\r
94 \r
95 CWVProtectionDomain::~CWVProtectionDomain()\r
96 {\r
97         DWORD   bytes;\r
98         HRESULT hr;\r
99 \r
100         if (m_Id != 0) {\r
101                 m_pVerbs->pre_deallocate_pd(m_hVerbsPd);\r
102                 hr = WvDeviceIoControl(m_hFile, WV_IOCTL_PD_DEALLOCATE, &m_Id, sizeof m_Id,\r
103                                                            NULL, 0, &bytes, NULL) ?\r
104                                                            WV_SUCCESS : HRESULT_FROM_WIN32(GetLastError());\r
105                 m_pVerbs->post_deallocate_pd(m_hVerbsPd, (ib_api_status_t) hr);\r
106         }\r
107         m_pDevice->Release();\r
108 }\r
109 \r
110 STDMETHODIMP CWVProtectionDomain::\r
111 QueryInterface(REFIID riid, LPVOID FAR* ppvObj)\r
112 {\r
113         if (riid != IID_IUnknown && riid != IID_IWVProtectionDomain) {\r
114                 *ppvObj = NULL;\r
115                 return E_NOINTERFACE;\r
116         }\r
117 \r
118         *ppvObj = this;\r
119         AddRef();\r
120         return WV_SUCCESS;\r
121 }\r
122 \r
123 STDMETHODIMP_(ULONG) CWVProtectionDomain::\r
124 AddRef(void)\r
125 {\r
126         return CWVBase::AddRef();\r
127 }\r
128 \r
129 STDMETHODIMP_(ULONG) CWVProtectionDomain::\r
130 Release(void)\r
131 {\r
132         return CWVBase::Release();\r
133 }\r
134 \r
135 STDMETHODIMP CWVProtectionDomain::\r
136 CancelOverlappedRequests(void)\r
137 {\r
138         DWORD   bytes;\r
139 \r
140         return WvDeviceIoControl(m_hFile, WV_IOCTL_PD_CANCEL, &m_Id, sizeof m_Id,\r
141                                                          NULL, 0, &bytes, NULL) ?\r
142                                                          WV_SUCCESS : HRESULT_FROM_WIN32(GetLastError());\r
143 }\r
144 \r
145 STDMETHODIMP CWVProtectionDomain::\r
146 GetOverlappedResult(OVERLAPPED *pOverlapped,\r
147                                         DWORD *pNumberOfBytesTransferred, BOOL bWait)\r
148 {\r
149         ::GetOverlappedResult(m_hFile, pOverlapped, pNumberOfBytesTransferred, bWait);\r
150         return (HRESULT) pOverlapped->Internal;\r
151 }\r
152 \r
153 STDMETHODIMP CWVProtectionDomain::\r
154 CreateSharedReceiveQueue(SIZE_T MaxWr, SIZE_T MaxSge,\r
155                                                  SIZE_T SrqLimit, IWVSharedReceiveQueue** ppSrq)\r
156 {\r
157         return CWVSharedReceiveQueue::CreateInstance(this, MaxWr, MaxSge,\r
158                                                                                                  SrqLimit, ppSrq);\r
159 }\r
160 \r
161 STDMETHODIMP CWVProtectionDomain::\r
162 CreateConnectQueuePair(WV_QP_CREATE* pAttributes, IWVConnectQueuePair** ppQp)\r
163 {\r
164         return CWVConnectQueuePair::CreateInstance(this, pAttributes, ppQp);\r
165 }\r
166 \r
167 STDMETHODIMP CWVProtectionDomain::\r
168 CreateDatagramQueuePair(WV_QP_CREATE* pAttributes, IWVDatagramQueuePair** ppQp)\r
169 {\r
170         return CWVDatagramQueuePair::CreateInstance(this, pAttributes, ppQp);\r
171 }\r
172 \r
173 STDMETHODIMP CWVProtectionDomain::\r
174 RegisterMemory(const VOID* pBuffer, SIZE_T BufferLength, DWORD AccessFlags,\r
175                            OVERLAPPED* pOverlapped, WV_MEMORY_KEYS *pKeys)\r
176 {\r
177         WV_IO_MEMORY_REGISTER   reg;\r
178         DWORD                                   bytes;\r
179         HRESULT                                 hr;\r
180 \r
181         reg.Id = m_Id;\r
182         reg.Address = (UINT64) (ULONG_PTR) pBuffer;\r
183         reg.BufferLength = BufferLength;\r
184         reg.AccessFlags = AccessFlags;\r
185         reg.Reserved = 0;\r
186 \r
187         if (WvDeviceIoControl(m_hFile, WV_IOCTL_MEMORY_REGISTER, &reg, sizeof reg,\r
188                                                   pKeys, sizeof WV_MEMORY_KEYS, &bytes, pOverlapped)) {\r
189                 hr = WV_SUCCESS;\r
190         } else {\r
191                 hr = HRESULT_FROM_WIN32(GetLastError());\r
192         }\r
193 \r
194         return hr;\r
195 }\r
196 \r
197 STDMETHODIMP CWVProtectionDomain::\r
198 DeregisterMemory(UINT32 Lkey, OVERLAPPED* pOverlapped)\r
199 {\r
200         WV_IO_ID        id;\r
201         DWORD           bytes;\r
202         HRESULT         hr;\r
203 \r
204         id.Id = m_Id;\r
205         id.Data = Lkey;\r
206         hr = WvDeviceIoControl(m_hFile, WV_IOCTL_MEMORY_DEREGISTER, &id, sizeof id,\r
207                                                    NULL, 0, &bytes, pOverlapped) ?\r
208                                                    WV_SUCCESS : HRESULT_FROM_WIN32(GetLastError());\r
209         return hr;\r
210 }\r
211 \r
212 STDMETHODIMP CWVProtectionDomain::\r
213 AllocateMemoryWindow(IWVMemoryWindow** ppMw)\r
214 {\r
215         return CWVMemoryWindow::CreateInstance(this, ppMw);\r
216 }\r
217 \r
218 STDMETHODIMP CWVProtectionDomain::\r
219 CreateAddressHandle(WV_ADDRESS_VECTOR* pAddress, IWVAddressHandle** ppAh, ULONG_PTR *pAhKey)\r
220 {\r
221         return CWVAddressHandle::CreateInstance(this, pAddress, ppAh, pAhKey);\r
222 }\r
223 \r
224 \r
225 //-----------------------\r
226 // Memory Window routines\r
227 //-----------------------\r
228 \r
229 CWVMemoryWindow::CWVMemoryWindow(CWVProtectionDomain *pPd)\r
230 {\r
231         pPd->AddRef();\r
232         m_pPd = pPd;\r
233         m_pVerbs = pPd->m_pVerbs;\r
234         m_hFile = pPd->m_hFile;\r
235         m_hVerbsMw = NULL;\r
236 }\r
237 \r
238 STDMETHODIMP CWVMemoryWindow::\r
239 Allocate(void)\r
240 {\r
241         WV_IO_ID                *pId;\r
242         DWORD                   bytes;\r
243         ib_api_status_t stat;\r
244         HRESULT                 hr;\r
245         ci_umv_buf_t    verbsData;\r
246         CWVBuffer               buf;\r
247 \r
248         stat = m_pVerbs->pre_create_mw(m_pPd->m_hVerbsPd, &verbsData, &m_hVerbsMw);\r
249         if (stat != IB_SUCCESS) {\r
250                 return WvConvertIbStatus(stat);\r
251         }\r
252 \r
253         bytes = sizeof WV_IO_ID + max(verbsData.input_size, verbsData.output_size);\r
254         pId = (WV_IO_ID *) buf.Get(bytes);\r
255         if (pId == NULL) {\r
256                 hr = WV_NO_MEMORY;\r
257                 goto post;\r
258         }\r
259 \r
260         pId->Id = m_pPd->m_Id;\r
261         pId->VerbInfo = verbsData.command;\r
262         RtlCopyMemory(pId + 1, (void *) (ULONG_PTR) verbsData.p_inout_buf,\r
263                                   verbsData.input_size);\r
264 \r
265         if (WvDeviceIoControl(m_hFile, WV_IOCTL_MW_ALLOCATE,\r
266                                                   pId, sizeof WV_IO_ID + verbsData.input_size,\r
267                                                   pId, sizeof WV_IO_ID + verbsData.output_size,\r
268                                                   &bytes, NULL)) {\r
269                 hr = WV_SUCCESS;\r
270                 m_Id = pId->Id;\r
271                 m_Rkey = pId->Data;\r
272         } else {\r
273                 hr = HRESULT_FROM_WIN32(GetLastError());\r
274         }\r
275 \r
276         verbsData.status = pId->VerbInfo;\r
277         RtlCopyMemory((void *) (ULONG_PTR) verbsData.p_inout_buf, pId + 1,\r
278                                   verbsData.output_size);\r
279         buf.Put();\r
280 \r
281 post:\r
282         m_pVerbs->post_create_mw(m_pPd->m_hVerbsPd, (ib_api_status_t) hr,\r
283                                                          m_Rkey, &m_hVerbsMw, &verbsData);\r
284         return hr;\r
285 }\r
286 \r
287 CWVMemoryWindow::~CWVMemoryWindow()\r
288 {\r
289         DWORD   bytes;\r
290         HRESULT hr;\r
291 \r
292         if (m_Id != 0) {\r
293                 m_pVerbs->pre_destroy_mw(m_hVerbsMw);\r
294                 hr = WvDeviceIoControl(m_hFile, WV_IOCTL_MW_DEALLOCATE,\r
295                                                            &m_Id, sizeof m_Id, NULL, 0, &bytes, NULL) ?\r
296                                                            WV_SUCCESS : HRESULT_FROM_WIN32(GetLastError());\r
297                 m_pVerbs->post_destroy_mw(m_hVerbsMw, (ib_api_status_t) hr);\r
298         }\r
299         m_pPd->Release();\r
300 }\r
301 \r
302 STDMETHODIMP CWVMemoryWindow::\r
303 QueryInterface(REFIID riid, LPVOID FAR* ppvObj)\r
304 {\r
305         if (riid != IID_IUnknown && riid != IID_IWVMemoryWindow) {\r
306                 *ppvObj = NULL;\r
307                 return E_NOINTERFACE;\r
308         }\r
309 \r
310         *ppvObj = this;\r
311         AddRef();\r
312         return WV_SUCCESS;\r
313 }\r
314 \r
315 STDMETHODIMP_(ULONG) CWVMemoryWindow::\r
316 AddRef(void)\r
317 {\r
318         return CWVBase::AddRef();\r
319 }\r
320 \r
321 STDMETHODIMP_(ULONG) CWVMemoryWindow::\r
322 Release(void)\r
323 {\r
324         return CWVBase::Release();\r
325 }\r
326 \r
327 \r
328 //------------------------\r
329 // Address Handle routines\r
330 //------------------------\r
331 \r
332 CWVAddressHandle::CWVAddressHandle(CWVProtectionDomain *pPd)\r
333 {\r
334         pPd->AddRef();\r
335         m_pPd = pPd;\r
336         m_pVerbs = pPd->m_pVerbs;\r
337         m_hFile = pPd->m_hFile;\r
338         m_hVerbsAh = NULL;\r
339 }\r
340 \r
341 STDMETHODIMP CWVAddressHandle::\r
342 Create(WV_ADDRESS_VECTOR* pAddress)\r
343 {\r
344         WV_IO_AH_CREATE *pav;\r
345         DWORD                   bytes;\r
346         ib_api_status_t stat;\r
347         HRESULT                 hr;\r
348         ci_umv_buf_t    verbsData;\r
349         ib_av_attr_t    attr;\r
350         CWVBuffer               buf;\r
351 \r
352         hr = ConvertAv(&attr, pAddress);\r
353         if (FAILED(hr)) {\r
354                 return hr;\r
355         }\r
356 \r
357         stat = m_pVerbs->pre_create_av(m_pPd->m_hVerbsPd, &attr, &verbsData, &m_hVerbsAh);\r
358         if (stat != IB_SUCCESS) {\r
359                 if (stat == IB_VERBS_PROCESSING_DONE) {\r
360                         m_Id = (ULONG_PTR) m_hVerbsAh;\r
361                 }\r
362                 return WvConvertIbStatus(stat);\r
363         }\r
364 \r
365         bytes = sizeof WV_IO_AH_CREATE + max(verbsData.input_size, verbsData.output_size);\r
366         pav = (WV_IO_AH_CREATE *) buf.Get(bytes);\r
367         if (pav == NULL) {\r
368                 hr = WV_NO_MEMORY;\r
369                 goto post;\r
370         }\r
371 \r
372         pav->Id.Id = m_pPd->m_Id;\r
373         pav->Id.VerbInfo = verbsData.command;\r
374         RtlCopyMemory(&pav->AddressVector, pAddress, sizeof(pav->AddressVector));\r
375         RtlCopyMemory(pav + 1, (void *) (ULONG_PTR) verbsData.p_inout_buf,\r
376                                   verbsData.input_size);\r
377 \r
378         if (WvDeviceIoControl(m_hFile, WV_IOCTL_AH_CREATE,\r
379                                                   pav, sizeof WV_IO_AH_CREATE + verbsData.input_size,\r
380                                                   pav, sizeof WV_IO_AH_CREATE + verbsData.output_size,\r
381                                                   &bytes, NULL)) {\r
382                 hr = WV_SUCCESS;\r
383                 m_Id = pav->Id.Id;\r
384         } else {\r
385                 hr = HRESULT_FROM_WIN32(GetLastError());\r
386         }\r
387 \r
388         verbsData.status = pav->Id.VerbInfo;\r
389         RtlCopyMemory((void *) (ULONG_PTR) verbsData.p_inout_buf, pav + 1,\r
390                                   verbsData.output_size);\r
391         buf.Put();\r
392 \r
393 post:\r
394         m_pVerbs->post_create_av(m_pPd->m_hVerbsPd, (ib_api_status_t) hr,\r
395                                                          &m_hVerbsAh, &verbsData);\r
396         return hr;\r
397 }\r
398 \r
399 CWVAddressHandle::~CWVAddressHandle()\r
400 {\r
401         DWORD                   bytes;\r
402         HRESULT                 hr;\r
403         ib_api_status_t stat;\r
404 \r
405         if (m_Id != 0) {\r
406                 stat = m_pVerbs->pre_destroy_av(m_hVerbsAh);\r
407                 if (stat != IB_VERBS_PROCESSING_DONE) {\r
408                         hr = WvDeviceIoControl(m_hFile, WV_IOCTL_AH_DESTROY,\r
409                                                                    &m_Id, sizeof m_Id, NULL, 0, &bytes, NULL) ?\r
410                                                                    WV_SUCCESS : HRESULT_FROM_WIN32(GetLastError());\r
411                         m_pVerbs->post_destroy_av(m_hVerbsAh, (ib_api_status_t) hr);\r
412                 }\r
413         }\r
414         m_pPd->Release();\r
415 }\r
416 \r
417 STDMETHODIMP CWVAddressHandle::\r
418 QueryInterface(REFIID riid, LPVOID FAR* ppvObj)\r
419 {\r
420         if (riid != IID_IUnknown && riid != IID_IWVAddressHandle) {\r
421                 *ppvObj = NULL;\r
422                 return E_NOINTERFACE;\r
423         }\r
424 \r
425         *ppvObj = this;\r
426         AddRef();\r
427         return WV_SUCCESS;\r
428 }\r
429 \r
430 STDMETHODIMP_(ULONG) CWVAddressHandle::\r
431 AddRef(void)\r
432 {\r
433         return CWVBase::AddRef();\r
434 }\r
435 \r
436 STDMETHODIMP_(ULONG) CWVAddressHandle::\r
437 Release(void)\r
438 {\r
439         return CWVBase::Release();\r
440 }\r
441 \r
442 STDMETHODIMP CWVAddressHandle::\r
443 ConvertAv(ib_av_attr_t *pVerbsAv, WV_ADDRESS_VECTOR *pAv)\r
444 {\r
445         DWORD index;\r
446         HRESULT hr;\r
447 \r
448         pVerbsAv->grh_valid = pAv->Route.Valid;\r
449         if (pVerbsAv->grh_valid) {\r
450                 hr = m_pPd->m_pDevice->FindGid(pAv->PortNumber, &pAv->Route.SGid, &index);\r
451                 if (FAILED(hr)) {\r
452                         return hr;\r
453                 }\r
454 \r
455                 pVerbsAv->grh.resv1 = (UINT16) index;\r
456                 pVerbsAv->grh.ver_class_flow =\r
457                         _byteswap_ulong(_byteswap_ulong(pAv->Route.FlowLabel) |\r
458                                                          (pAv->Route.TrafficClass << 20));\r
459                 pVerbsAv->grh.hop_limit = pAv->Route.HopLimit;\r
460                 RtlCopyMemory(&pVerbsAv->grh.src_gid, &pAv->Route.SGid, sizeof(pAv->Route.SGid));\r
461                 RtlCopyMemory(&pVerbsAv->grh.dest_gid, &pAv->Route.DGid, sizeof(pAv->Route.DGid));\r
462         }\r
463 \r
464         pVerbsAv->port_num = pAv->PortNumber;\r
465         pVerbsAv->sl = pAv->ServiceLevel;\r
466         pVerbsAv->dlid = pAv->DLid;\r
467         pVerbsAv->static_rate = pAv->StaticRate;\r
468         pVerbsAv->path_bits = pAv->SourcePathBits;\r
469 \r
470         return WV_SUCCESS;\r
471 }