netdirect: add winverbs ND provider
[mirror/winof/.git] / ulp / netdirect / user / nd_ep.cpp
1 /*\r
2  * Copyright (c) 2009 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 AND\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 "nd_ep.h"\r
31 #include "nd_adapter.h"\r
32 #include "nd_connect.h"\r
33 #include "nd_cq.h"\r
34 #include "nd_mw.h"\r
35 #include <netinet/in.h>\r
36 \r
37 \r
38 CNDEndpoint::CNDEndpoint(CNDConnector *pConnector)\r
39 {\r
40         pConnector->AddRef();\r
41         m_pConnector = pConnector;\r
42         m_pWvQp = NULL;\r
43         m_pInboundCq = NULL;\r
44         m_pOutboundCq = NULL;\r
45 }\r
46 \r
47 STDMETHODIMP CNDEndpoint::\r
48 Init(CNDCompletionQueue* pInboundCq, CNDCompletionQueue* pOutboundCq,\r
49          SIZE_T nInboundEntries, SIZE_T nOutboundEntries,\r
50          SIZE_T nInboundSge, SIZE_T nOutboundSge,\r
51          SIZE_T InboundReadLimit, SIZE_T OutboundReadLimit,\r
52          SIZE_T* pMaxInlineData)\r
53 {\r
54         WV_QP_CREATE create;\r
55         WV_QP_ATTRIBUTES attr;\r
56         WV_DEVICE_ADDRESS *addr;\r
57         DWORD opts;\r
58         HRESULT hr;\r
59 \r
60         m_pInboundCq->AddRef();\r
61         m_pOutboundCq->AddRef();\r
62         m_InitiatorDepth = OutboundReadLimit;\r
63         m_ResponderResources = InboundReadLimit;\r
64 \r
65         RtlZeroMemory(&create, sizeof create);\r
66         create.pSendCq = pOutboundCq->m_pWvCq;\r
67         create.pReceiveCq = pInboundCq->m_pWvCq;\r
68         create.Context = this;\r
69         create.SendDepth = nOutboundEntries;\r
70         create.SendSge = nOutboundSge;\r
71         create.ReceiveDepth = nInboundEntries;\r
72         create.ReceiveSge = nInboundSge;\r
73         create.InitiatorDepth = OutboundReadLimit;\r
74         create.ResponderResources = InboundReadLimit;\r
75         create.QpType = WvQpTypeRc;\r
76         \r
77         hr = m_pConnector->m_pAdapter->m_pWvPd->CreateConnectQueuePair(&create, &m_pWvQp);\r
78         if (FAILED(hr)) {\r
79                 return hr;\r
80         }\r
81 \r
82         opts = WV_QP_ATTR_STATE | WV_QP_ATTR_PORT_NUMBER | WV_QP_ATTR_PKEY_INDEX;\r
83         attr.QpState = WvQpStateInit;\r
84         addr = &m_pConnector->m_pAdapter->m_DevAddress;\r
85         attr.AddressVector.PortNumber = addr->PortNumber;\r
86         hr = m_pConnector->m_pAdapter->m_pWvDevice->FindPkey(addr->PortNumber, addr->Pkey,\r
87                                                                                                                  &attr.PkeyIndex);\r
88         if (FAILED(hr)) {\r
89                 return hr;\r
90         }\r
91 \r
92         hr = m_pWvQp->Modify(&attr, opts, NULL);\r
93         if (FAILED(hr)) {\r
94                 return hr;\r
95         }\r
96 \r
97         *pMaxInlineData = 0;\r
98         return ND_SUCCESS;\r
99 }\r
100 \r
101 CNDEndpoint::~CNDEndpoint()\r
102 {\r
103         if (m_pWvQp != NULL) {\r
104                 m_pWvQp->Release();\r
105         }\r
106         if (m_pInboundCq != NULL) {\r
107                 m_pInboundCq->Release();\r
108         }\r
109         if (m_pOutboundCq != NULL) {\r
110                 m_pOutboundCq->Release();\r
111         }\r
112         m_pConnector->Release();\r
113 }\r
114 \r
115 STDMETHODIMP CNDEndpoint::\r
116 QueryInterface(REFIID riid, LPVOID FAR* ppvObj)\r
117 {\r
118         if (riid != IID_IUnknown && riid != IID_INDEndpoint) {\r
119                 *ppvObj = NULL;\r
120                 return E_NOINTERFACE;\r
121         }\r
122 \r
123         *ppvObj = this;\r
124         AddRef();\r
125         return ND_SUCCESS;\r
126 }\r
127 \r
128 STDMETHODIMP_(ULONG) CNDEndpoint::\r
129 AddRef(void)\r
130 {\r
131         return CNDBase::AddRef();\r
132 }\r
133 \r
134 STDMETHODIMP_(ULONG) CNDEndpoint::\r
135 Release(void)\r
136 {\r
137         return CNDBase::Release();\r
138 }\r
139 \r
140 STDMETHODIMP CNDEndpoint::\r
141 Flush(void)\r
142 {\r
143         return ND_SUCCESS;\r
144 }\r
145 \r
146 STDMETHODIMP_(void) CNDEndpoint::\r
147 StartRequestBatch(void)\r
148 {\r
149         // no-op\r
150 }\r
151 \r
152 STDMETHODIMP_(void) CNDEndpoint::\r
153 SubmitRequestBatch(void)\r
154 {\r
155         // no-op\r
156 }\r
157 \r
158 STDMETHODIMP_(void) CNDEndpoint::\r
159 ConvertSgl(const ND_SGE* pSgl, SIZE_T nSge, WV_SGE* pWvSgl)\r
160 {\r
161         SIZE_T i;\r
162 \r
163         for (i = 0; i < nSge; i++) {\r
164                 pWvSgl[i].pAddress = pSgl[i].pAddr;\r
165                 pWvSgl[i].Length = (UINT32) pSgl[i].Length;\r
166                 pWvSgl[i].Lkey = pSgl[i].hMr ? ((ND_MR *) pSgl[i].hMr)->Keys.Lkey : 0;\r
167         }\r
168 }\r
169 \r
170 STDMETHODIMP_(DWORD) CNDEndpoint::\r
171 ConvertSendFlags(DWORD Flags)\r
172 {\r
173         DWORD opts = 0;\r
174 \r
175         if (!(Flags & ND_OP_FLAG_SILENT_SUCCESS)) {\r
176                 opts |= WV_SEND_SIGNALED;\r
177         }\r
178         if (Flags & ND_OP_FLAG_READ_FENCE) {\r
179                 opts |= WV_SEND_FENCE;\r
180         }\r
181         if (Flags & ND_OP_FLAG_SEND_AND_SOLICIT_EVENT) {\r
182                 opts |= WV_SEND_SOLICITED;\r
183         }\r
184         return opts;\r
185 }\r
186 \r
187 STDMETHODIMP_(DWORD) CNDEndpoint::\r
188 ConvertAccessFlags(DWORD Flags)\r
189 {\r
190         DWORD opts = 0;\r
191 \r
192         if (!(Flags & ND_OP_FLAG_ALLOW_READ)) {\r
193                 opts |= WV_ACCESS_REMOTE_READ;\r
194         }\r
195         if (Flags & ND_OP_FLAG_ALLOW_WRITE) {\r
196                 opts |= WV_ACCESS_REMOTE_WRITE;\r
197         }\r
198         return opts;\r
199 }\r
200 \r
201 STDMETHODIMP CNDEndpoint::\r
202 Send(ND_RESULT* pResult, const ND_SGE* pSgl, SIZE_T nSge, DWORD Flags)\r
203 {\r
204         WV_SGE sgl[ND_MAX_SGE];\r
205         DWORD opts;\r
206 \r
207         ConvertSgl(pSgl, nSge, sgl);\r
208         opts = ConvertSendFlags(Flags) | (pSgl[0].hMr ? 0 : WV_SEND_INLINE);\r
209         return m_pWvQp->Send((UINT64) pResult, sgl, nSge, opts, 0);\r
210 }\r
211 \r
212 STDMETHODIMP CNDEndpoint::\r
213 SendAndInvalidate(ND_RESULT* pResult, const ND_SGE* pSgl, SIZE_T nSge,\r
214                                   const ND_MW_DESCRIPTOR* pRemoteMwDescriptor, DWORD Flags)\r
215 {\r
216         return Send(pResult, pSgl, nSge, Flags);\r
217 }\r
218 \r
219 STDMETHODIMP CNDEndpoint::\r
220 Receive(ND_RESULT* pResult, const ND_SGE* pSgl, SIZE_T nSge)\r
221 {\r
222         WV_SGE sgl[ND_MAX_SGE];\r
223 \r
224         ConvertSgl(pSgl, nSge, sgl);\r
225         return m_pWvQp->PostReceive((UINT64) pResult, sgl, nSge);\r
226 }\r
227 \r
228 STDMETHODIMP CNDEndpoint::\r
229 Bind(ND_RESULT* pResult, ND_MR_HANDLE hMr, INDMemoryWindow* pMw,\r
230          const void* pBuffer, SIZE_T BufferSize, DWORD Flags,\r
231          ND_MW_DESCRIPTOR* pMwDescriptor)\r
232 {\r
233         CNDMemoryWindow *mw = (CNDMemoryWindow *) pMw;\r
234         ND_MR *mr = (ND_MR *) hMr;\r
235         WV_SGE sge;\r
236 \r
237         pMwDescriptor->Base = htonll((UINT64) (ULONG_PTR) pBuffer);\r
238         pMwDescriptor->Length = htonll(BufferSize);\r
239         pMwDescriptor->Token = mr->Keys.Rkey;\r
240 \r
241         RtlZeroMemory(&sge, sizeof sge);\r
242         return m_pWvQp->Write((UINT64) pResult, &sge, 1, ConvertSendFlags(Flags),\r
243                                                   0, NULL, 0);\r
244 }\r
245 \r
246 STDMETHODIMP CNDEndpoint::\r
247 Invalidate(ND_RESULT* pResult, INDMemoryWindow* pMw, DWORD Flags)\r
248 {\r
249         WV_SGE sge;\r
250 \r
251         RtlZeroMemory(&sge, sizeof sge);\r
252         return m_pWvQp->Write((UINT64) pResult, &sge, 1, ConvertSendFlags(Flags),\r
253                                                   0, NULL, 0);\r
254 }\r
255 \r
256 STDMETHODIMP CNDEndpoint::\r
257 Read(ND_RESULT* pResult, const ND_SGE* pSgl, SIZE_T nSge,\r
258          const ND_MW_DESCRIPTOR* pRemoteMwDescriptor, ULONGLONG Offset, DWORD Flags)\r
259 {\r
260         WV_SGE sgl[ND_MAX_SGE];\r
261         DWORD opts;\r
262 \r
263         ConvertSgl(pSgl, nSge, sgl);\r
264         opts = ConvertSendFlags(Flags) | (pSgl[0].hMr ? 0 : WV_SEND_INLINE);\r
265         return m_pWvQp->Read((UINT64) pResult, sgl, nSge, opts,\r
266                                                  pRemoteMwDescriptor->Base + htonll(Offset),\r
267                                                  pRemoteMwDescriptor->Token);\r
268 }\r
269 \r
270 STDMETHODIMP CNDEndpoint::\r
271 Write(ND_RESULT* pResult, const ND_SGE* pSgl, SIZE_T nSge,\r
272           const ND_MW_DESCRIPTOR* pRemoteMwDescriptor, ULONGLONG Offset, DWORD Flags)\r
273 {\r
274         WV_SGE sgl[ND_MAX_SGE];\r
275         DWORD opts;\r
276 \r
277         ConvertSgl(pSgl, nSge, sgl);\r
278         opts = ConvertSendFlags(Flags) | (pSgl[0].hMr ? 0 : WV_SEND_INLINE);\r
279         return m_pWvQp->Write((UINT64) pResult, sgl, nSge, opts, 0,\r
280                                                   pRemoteMwDescriptor->Base + htonll(Offset),\r
281                                                   pRemoteMwDescriptor->Token);\r
282 }\r