winverbs/nd: do not convert timeout status value
[mirror/winof/.git] / ulp / libibverbs / src / verbs.cpp
1 /*\r
2  * Copyright (c) 2005 Topspin Communications.  All rights reserved.\r
3  * Copyright (c) 2006, 2007 Cisco Systems, Inc.  All rights reserved.\r
4  * Copyright (c) 2008-2009 Intel Corporation.  All rights reserved.\r
5  *\r
6  * This software is available to you under the OpenIB.org BSD license\r
7  * below:\r
8  *\r
9  *     Redistribution and use in source and binary forms, with or\r
10  *     without modification, are permitted provided that the following\r
11  *     conditions are met:\r
12  *\r
13  *      - Redistributions of source code must retain the above\r
14  *        copyright notice, this list of conditions and the following\r
15  *        disclaimer.\r
16  *\r
17  *      - Redistributions in binary form must reproduce the above\r
18  *        copyright notice, this list of conditions and the following\r
19  *        disclaimer in the documentation and/or other materials\r
20  *        provided with the distribution.\r
21  *\r
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
25  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
26  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
27  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
28  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
29  * SOFTWARE.\r
30  */\r
31 \r
32 #include <windows.h>\r
33 #include <winsock2.h>\r
34 #include <stdio.h>\r
35 #include <netinet/in.h>\r
36 \r
37 #include <infiniband/verbs.h>\r
38 #include <comp_channel.h>\r
39 #include "ibverbs.h"\r
40 \r
41 \r
42 __declspec(dllexport)\r
43 int ibv_rate_to_mult(enum ibv_rate rate)\r
44 {\r
45         switch (rate) {\r
46         case IBV_RATE_2_5_GBPS: return  1;\r
47         case IBV_RATE_5_GBPS:   return  2;\r
48         case IBV_RATE_10_GBPS:  return  4;\r
49         case IBV_RATE_20_GBPS:  return  8;\r
50         case IBV_RATE_30_GBPS:  return 12;\r
51         case IBV_RATE_40_GBPS:  return 16;\r
52         case IBV_RATE_60_GBPS:  return 24;\r
53         case IBV_RATE_80_GBPS:  return 32;\r
54         case IBV_RATE_120_GBPS: return 48;\r
55         default:                                return -1;\r
56         }\r
57 }\r
58 \r
59 __declspec(dllexport)\r
60 enum ibv_rate mult_to_ibv_rate(int mult)\r
61 {\r
62         switch (mult) {\r
63         case 1:  return IBV_RATE_2_5_GBPS;\r
64         case 2:  return IBV_RATE_5_GBPS;\r
65         case 4:  return IBV_RATE_10_GBPS;\r
66         case 8:  return IBV_RATE_20_GBPS;\r
67         case 12: return IBV_RATE_30_GBPS;\r
68         case 16: return IBV_RATE_40_GBPS;\r
69         case 24: return IBV_RATE_60_GBPS;\r
70         case 32: return IBV_RATE_80_GBPS;\r
71         case 48: return IBV_RATE_120_GBPS;\r
72         default: return IBV_RATE_MAX;\r
73         }\r
74 }\r
75 \r
76 static int ibv_find_gid_index(struct ibv_context *context, uint8_t port_num,\r
77                                                           union ibv_gid *gid)\r
78 {\r
79         union ibv_gid sgid;\r
80         int i = 0, ret;\r
81 \r
82         do {\r
83                 ret = ibv_query_gid(context, port_num, i++, &sgid);\r
84         } while (!ret && memcmp(&sgid, gid, sizeof *gid));\r
85 \r
86         return ret ? ret : i - 1;\r
87 }\r
88 \r
89 static void ibv_convert_ah_attr(struct ibv_context *context,\r
90                                                                 WV_ADDRESS_VECTOR *av, struct ibv_ah_attr *attr)\r
91 {\r
92         WV_GID gid;\r
93 \r
94         av->Route.Valid = attr->is_global;\r
95         if (av->Route.Valid) {\r
96                 context->cmd_if->QueryGid(attr->port_num, attr->grh.sgid_index, &gid);\r
97 \r
98                 memcpy(&av->Route.DGid, &attr->grh.dgid, sizeof(av->Route.DGid));\r
99                 memcpy(&av->Route.SGid, &gid, sizeof(av->Route.SGid));\r
100                 av->Route.TrafficClass = attr->grh.traffic_class;\r
101                 av->Route.FlowLabel =  htonl(attr->grh.flow_label);\r
102                 av->Route.HopLimit = attr->grh.hop_limit;\r
103         }\r
104 \r
105         av->DLid = htons(attr->dlid);\r
106         av->ServiceLevel = attr->sl;\r
107         av->SourcePathBits = attr->src_path_bits;\r
108         av->StaticRate = attr->static_rate;\r
109         av->PortNumber = attr->port_num;\r
110 }\r
111 \r
112 static void ibv_convert_av(struct ibv_context *context,\r
113                                                    struct ibv_ah_attr *attr, WV_ADDRESS_VECTOR *av)\r
114 {\r
115         WV_GID gid;\r
116 \r
117         attr->is_global = av->Route.Valid;\r
118         if (attr->is_global) {\r
119                 memcpy(&attr->grh.dgid, &av->Route.DGid, sizeof(attr->grh.dgid));\r
120                 attr->grh.flow_label = ntohl(av->Route.FlowLabel);\r
121                 attr->grh.traffic_class = av->Route.TrafficClass;\r
122                 attr->grh.hop_limit = av->Route.HopLimit;\r
123                 attr->grh.sgid_index = (uint8_t) ibv_find_gid_index(context, av->PortNumber,\r
124                                                                                                                         (ibv_gid *) &av->Route.SGid);\r
125         }\r
126 \r
127         attr->dlid = ntohs(av->DLid);\r
128         attr->sl = av->ServiceLevel;\r
129         attr->src_path_bits     = av->SourcePathBits;\r
130         attr->static_rate = av->StaticRate;\r
131         attr->port_num = av->PortNumber;\r
132 }\r
133 \r
134 __declspec(dllexport)\r
135 int ibv_query_device(struct ibv_context *context,\r
136                                          struct ibv_device_attr *device_attr)\r
137 {\r
138         WV_DEVICE_ATTRIBUTES attr;\r
139         HRESULT hr;\r
140 \r
141         hr = context->cmd_if->Query(&attr);\r
142         if (FAILED(hr)) {\r
143                 return hr;\r
144         }\r
145 \r
146         sprintf(device_attr->fw_ver, "0x%I64x", attr.FwVersion);\r
147         device_attr->node_guid = attr.NodeGuid;\r
148         device_attr->sys_image_guid = attr.SystemImageGuid;\r
149         device_attr->max_mr_size = attr.MaxMrSize;\r
150         device_attr->page_size_cap = attr.PageSizeCapabilityFlags;\r
151         device_attr->vendor_id = attr.VendorId;\r
152         device_attr->vendor_part_id = attr.VendorPartId;\r
153         device_attr->hw_ver = attr.HwVersion;\r
154         device_attr->max_qp = (int) attr.MaxQp;\r
155         device_attr->max_qp_wr = (int) attr.MaxQpWr;\r
156         device_attr->device_cap_flags = (int) attr.CapabilityFlags;\r
157         device_attr->max_sge = (int) attr.MaxSge;\r
158         device_attr->max_sge_rd = 0;\r
159         device_attr->max_cq = (int) attr.MaxCq;\r
160         device_attr->max_cqe = (int) attr.MaxCqEntries;\r
161         device_attr->max_mr = (int) attr.MaxMr;\r
162         device_attr->max_pd = (int) attr.MaxPd;\r
163         device_attr->max_qp_rd_atom = (int) attr.MaxQpResponderResources;;\r
164         device_attr->max_ee_rd_atom = 0;\r
165         device_attr->max_res_rd_atom = (int) attr.MaxResponderResources;\r
166         device_attr->max_qp_init_rd_atom = (int) attr.MaxQpInitiatorDepth;\r
167         device_attr->max_ee_init_rd_atom = 0;\r
168         device_attr->atomic_cap = (enum ibv_atomic_cap) attr.AtomicCapability;\r
169         device_attr->max_ee = 0;\r
170         device_attr->max_rdd = 0;\r
171         device_attr->max_mw = (int) attr.MaxMw;\r
172         device_attr->max_raw_ipv6_qp = 0;\r
173         device_attr->max_raw_ethy_qp = 0;\r
174         device_attr->max_mcast_grp = (int) attr.MaxMulticast;\r
175         device_attr->max_mcast_qp_attach = (int) attr.MaxQpAttach;\r
176         device_attr->max_total_mcast_qp_attach = (int) attr.MaxMulticastQp;\r
177         device_attr->max_ah = (int) attr.MaxAh;\r
178         device_attr->max_fmr = (int) attr.MaxFmr;\r
179         device_attr->max_map_per_fmr = (int) attr.MaxMapPerFmr;\r
180         device_attr->max_srq = (int) attr.MaxSrq;\r
181         device_attr->max_srq_wr = (int) attr.MaxSrqWr;\r
182         device_attr->max_srq_sge = (int) attr.MaxSrqSge;\r
183         device_attr->max_pkeys = (uint16_t) attr.MaxPkeys;\r
184         device_attr->local_ca_ack_delay = attr.LocalAckDelay;\r
185         device_attr->phys_port_cnt = attr.PhysPortCount;\r
186 \r
187         return 0;\r
188 }\r
189 \r
190 static enum ibv_mtu ibv_convert_mtu(UINT32 mtu)\r
191 {\r
192         switch (mtu) {\r
193         case 256:       return IBV_MTU_256;\r
194         case 512:       return IBV_MTU_512;\r
195         case 1024:      return IBV_MTU_1024;\r
196         case 2048:      return IBV_MTU_2048;\r
197         case 4096:      return IBV_MTU_4096;\r
198         default:        return (ibv_mtu) mtu;\r
199         }\r
200 }\r
201 \r
202 __declspec(dllexport)\r
203 int ibv_query_port(struct ibv_context *context, uint8_t port_num,\r
204                                    struct ibv_port_attr *port_attr)\r
205 {\r
206         WV_PORT_ATTRIBUTES attr;\r
207         HRESULT hr;\r
208         \r
209         hr = context->cmd_if->QueryPort(port_num, &attr);\r
210         if (FAILED(hr)) {\r
211                 return hr;\r
212         }\r
213 \r
214         port_attr->state = (enum ibv_port_state) attr.State;\r
215         port_attr->max_mtu = ibv_convert_mtu(attr.MaxMtu);\r
216         port_attr->active_mtu = ibv_convert_mtu(attr.ActiveMtu);\r
217         port_attr->gid_tbl_len = attr.GidTableLength;\r
218         port_attr->port_cap_flags = attr.PortCabilityFlags;\r
219         port_attr->max_msg_sz = attr.MaxMessageSize;\r
220         port_attr->bad_pkey_cntr = attr.BadPkeyCounter;\r
221         port_attr->qkey_viol_cntr = attr.QkeyViolationCounter;\r
222         port_attr->pkey_tbl_len = attr.PkeyTableLength;\r
223         port_attr->lid = ntohs(attr.Lid);\r
224         port_attr->sm_lid = ntohs(attr.SmLid);\r
225         port_attr->lmc = attr.Lmc;\r
226         port_attr->max_vl_num = attr.MaxVls;\r
227         port_attr->sm_sl = attr.SmSl;\r
228         port_attr->subnet_timeout = attr.SubnetTimeout;\r
229         port_attr->init_type_reply = attr.InitTypeReply;\r
230         port_attr->active_width = attr.ActiveWidth;\r
231         port_attr->active_speed = attr.ActiveSpeed;\r
232         port_attr->phys_state = attr.PhysicalState;\r
233 \r
234         return 0;\r
235 }\r
236 \r
237 __declspec(dllexport)\r
238 int ibv_query_gid(struct ibv_context *context, uint8_t port_num,\r
239                                   int index, union ibv_gid *gid)\r
240 {\r
241         return context->cmd_if->QueryGid(port_num, index, (WV_GID *) gid);\r
242 }\r
243 \r
244 __declspec(dllexport)\r
245 int ibv_query_pkey(struct ibv_context *context, uint8_t port_num,\r
246                                    int index, uint16_t *pkey)\r
247 {\r
248         return context->cmd_if->QueryPkey(port_num, (UINT16) index, pkey);\r
249 }\r
250 \r
251 __declspec(dllexport)\r
252 struct ibv_pd *ibv_alloc_pd(struct ibv_context *context)\r
253 {\r
254         struct ibv_pd *pd;\r
255         HRESULT hr;\r
256 \r
257         pd = new struct ibv_pd;\r
258         if (pd == NULL) {\r
259                 return NULL;\r
260         }\r
261 \r
262         pd->context = context;\r
263         hr = context->cmd_if->AllocateProtectionDomain(&pd->handle);\r
264         if (FAILED(hr)) {\r
265                 delete pd;\r
266                 return NULL;\r
267         }\r
268         return pd;\r
269 }\r
270 \r
271 __declspec(dllexport)\r
272 int ibv_dealloc_pd(struct ibv_pd *pd)\r
273 {\r
274         pd->handle->Release();\r
275         delete pd;\r
276         return 0;\r
277 }\r
278 \r
279 __declspec(dllexport)\r
280 struct ibv_mr *ibv_reg_mr(struct ibv_pd *pd, void *addr,\r
281                                                   size_t length, enum ibv_access_flags access)\r
282 {\r
283         struct ibv_mr *mr;\r
284         HRESULT hr;\r
285 \r
286         mr = new struct ibv_mr;\r
287         if (mr == NULL) {\r
288                 return NULL;\r
289         }\r
290 \r
291         mr->context = pd->context;\r
292         mr->pd = pd;\r
293         mr->addr = addr;\r
294         mr->length = length;\r
295         hr = pd->handle->RegisterMemory(addr, length, access, NULL,\r
296                                                                         (WV_MEMORY_KEYS *) &mr->lkey);\r
297         if (FAILED(hr)) {\r
298                 delete mr;\r
299                 return NULL;\r
300         }\r
301         mr->rkey = ntohl(mr->rkey);\r
302         return mr;\r
303 }\r
304 \r
305 __declspec(dllexport)\r
306 int ibv_dereg_mr(struct ibv_mr *mr)\r
307 {\r
308         HRESULT hr;\r
309 \r
310         hr = mr->pd->handle->DeregisterMemory(mr->lkey, NULL);\r
311         if (SUCCEEDED(hr)) {\r
312                 delete mr;\r
313         }\r
314         return hr;\r
315 }\r
316 \r
317 __declspec(dllexport)\r
318 struct ibv_comp_channel *ibv_create_comp_channel(struct ibv_context *context)\r
319 {\r
320         struct ibv_comp_channel *channel;\r
321 \r
322         channel = new struct ibv_comp_channel;\r
323         if (channel == NULL) {\r
324                 return NULL;\r
325         }\r
326 \r
327         CompChannelInit(&comp_mgr, &channel->comp_channel, INFINITE);\r
328         channel->context = context;\r
329         return channel;\r
330 }\r
331 \r
332 __declspec(dllexport)\r
333 int ibv_destroy_comp_channel(struct ibv_comp_channel *channel)\r
334 {\r
335         CompChannelCleanup(&channel->comp_channel);\r
336         delete channel;\r
337         return 0;\r
338 }\r
339 \r
340 __declspec(dllexport)\r
341 struct ibv_cq *ibv_create_cq(struct ibv_context *context, int cqe, void *cq_context,\r
342                                                          struct ibv_comp_channel *channel, int comp_vector)\r
343 {\r
344         struct ibv_cq *cq;\r
345         HRESULT hr;\r
346         SIZE_T entries;\r
347 \r
348         cq = new struct ibv_cq;\r
349         if (cq == NULL) {\r
350                 return NULL;\r
351         }\r
352 \r
353         cq->context = context;\r
354         cq->channel = channel;\r
355         cq->cq_context = cq_context;\r
356         cq->notify_cnt = 0;\r
357         cq->ack_cnt = 0;\r
358 \r
359         entries = cqe;\r
360         hr = context->cmd_if->CreateCompletionQueue(&entries, &cq->handle);\r
361         if (FAILED(hr)) {\r
362                 goto err;\r
363         }\r
364 \r
365         if (channel != NULL) {\r
366                 CompEntryInit(&channel->comp_channel, &cq->comp_entry);\r
367         } else {\r
368                 memset(&cq->comp_entry, 0, sizeof cq->comp_entry);\r
369         }\r
370 \r
371         cq->cqe = (uint32_t) entries;\r
372         return cq;\r
373 \r
374 err:\r
375         delete cq;\r
376         return NULL;\r
377 }\r
378 \r
379 __declspec(dllexport)\r
380 int ibv_resize_cq(struct ibv_cq *cq, int cqe)\r
381 {\r
382         HRESULT hr;\r
383         SIZE_T entries = cqe;\r
384 \r
385         hr = cq->handle->Resize(&entries);\r
386         if (SUCCEEDED(hr)) {\r
387                 cq->cqe = (int) entries;\r
388         }\r
389         return hr;\r
390 }\r
391 \r
392 __declspec(dllexport)\r
393 int ibv_req_notify_cq(struct ibv_cq *cq, int solicited_only)\r
394 {\r
395         HRESULT hr;\r
396 \r
397         if (InterlockedCompareExchange(&cq->comp_entry.Busy, 1, 0) == 0) {\r
398                 InterlockedIncrement(&cq->notify_cnt);\r
399                 hr = cq->handle->Notify(solicited_only ? WvCqSolicited : WvCqNextCompletion,\r
400                                                                 &cq->comp_entry.Overlap);\r
401                 if (SUCCEEDED(hr) || hr == WV_IO_PENDING) {\r
402                         hr = 0;\r
403                 } else {\r
404                         InterlockedExchange(&cq->comp_entry.Busy, 0);\r
405                         InterlockedDecrement(&cq->notify_cnt);\r
406                 }\r
407         } else {\r
408                 hr = 0;\r
409         }\r
410         return hr;\r
411 }\r
412 \r
413 __declspec(dllexport)\r
414 int ibv_poll_cq(struct ibv_cq *cq, int num_entries, struct ibv_wc *wc)\r
415 {\r
416         int n;\r
417 \r
418         num_entries = (int) cq->handle->Poll((WV_COMPLETION *) wc, num_entries);\r
419         for (n = 0; n < num_entries; n++) {\r
420                 wc[n].qp_num = ((ibv_qp *) wc[n].reserved)->qp_num;\r
421                 wc[n].src_qp = ntohl(wc[n].src_qp);\r
422                 wc[n].slid = ntohs(wc[n].slid);\r
423         }\r
424         return num_entries;\r
425 }\r
426 \r
427 __declspec(dllexport)\r
428 int ibv_destroy_cq(struct ibv_cq *cq)\r
429 {\r
430         cq->handle->CancelOverlappedRequests();\r
431         if (cq->channel != NULL) {\r
432                 if (CompEntryCancel(&cq->comp_entry)) {\r
433                         InterlockedIncrement(&cq->ack_cnt);\r
434                 }\r
435         }\r
436 \r
437         while (cq->ack_cnt < cq->notify_cnt)\r
438                 Sleep(0);\r
439         cq->handle->Release();\r
440         delete cq;\r
441         return 0;\r
442 }\r
443 \r
444 __declspec(dllexport)\r
445 int ibv_get_cq_event(struct ibv_comp_channel *channel,\r
446                                          struct ibv_cq **cq, void **cq_context)\r
447 {\r
448         COMP_ENTRY *entry;\r
449         DWORD ret;\r
450 \r
451         ret = CompChannelPoll(&channel->comp_channel, &entry);\r
452         if (!ret) {\r
453                 *cq = CONTAINING_RECORD(entry, struct ibv_cq, comp_entry);\r
454                 *cq_context = (*cq)->cq_context;\r
455         }\r
456 \r
457         return ret;\r
458 }\r
459 \r
460 __declspec(dllexport)\r
461 void ibv_ack_cq_events(struct ibv_cq *cq, unsigned int nevents)\r
462 {\r
463         InterlockedExchangeAdd(&cq->ack_cnt, (LONG) nevents);\r
464 }\r
465 \r
466 __declspec(dllexport)\r
467 struct ibv_srq *ibv_create_srq(struct ibv_pd *pd,\r
468                                                            struct ibv_srq_init_attr *srq_init_attr)\r
469 {\r
470         struct ibv_srq *srq;\r
471         HRESULT hr;\r
472 \r
473         srq = new struct ibv_srq;\r
474         if (srq == NULL) {\r
475                 return NULL;\r
476         }\r
477 \r
478         srq->context = pd->context;\r
479         srq->srq_context = srq_init_attr->srq_context;\r
480         srq->pd = pd;\r
481 \r
482         hr = pd->handle->CreateSharedReceiveQueue(srq_init_attr->attr.max_wr,\r
483                                                                                           srq_init_attr->attr.max_sge,\r
484                                                                                           srq_init_attr->attr.srq_limit,\r
485                                                                                           &srq->handle);\r
486         if (FAILED(hr)) {\r
487                 delete srq;\r
488                 return NULL;\r
489         }\r
490 \r
491         return srq;\r
492 }\r
493 \r
494 __declspec(dllexport)\r
495 int ibv_modify_srq(struct ibv_srq *srq,\r
496                                    struct ibv_srq_attr *srq_attr,\r
497                                    enum ibv_srq_attr_mask srq_attr_mask)\r
498 {\r
499         ibv_srq_attr attr;\r
500 \r
501         ibv_query_srq(srq, &attr);\r
502         if (srq_attr_mask & IBV_SRQ_MAX_WR) {\r
503                 attr.max_wr = srq_attr->max_wr;\r
504         }\r
505         if (srq_attr_mask & IBV_SRQ_LIMIT) {\r
506                 attr.srq_limit = srq_attr->srq_limit;\r
507         }\r
508 \r
509         return srq->handle->Modify(attr.max_wr, attr.srq_limit);\r
510 }\r
511 \r
512 __declspec(dllexport)\r
513 int ibv_post_srq_recv(struct ibv_srq *srq,\r
514                                           struct ibv_recv_wr *recv_wr,\r
515                                           struct ibv_recv_wr **bad_recv_wr)\r
516 {\r
517         HRESULT hr = 0;\r
518 \r
519         for (*bad_recv_wr = recv_wr; *bad_recv_wr != NULL && SUCCEEDED(hr);\r
520                  *bad_recv_wr = (*bad_recv_wr)->next) {\r
521                 hr = srq->handle->PostReceive((*bad_recv_wr)->wr_id,\r
522                                                                           (WV_SGE *) (*bad_recv_wr)->sg_list,\r
523                                                                           (*bad_recv_wr)->num_sge);\r
524         }\r
525         return hr;\r
526 }\r
527 \r
528 __declspec(dllexport)\r
529 int ibv_query_srq(struct ibv_srq *srq, struct ibv_srq_attr *srq_attr)\r
530 {\r
531         SIZE_T max_wr, max_sge, srq_limit;\r
532         HRESULT hr;\r
533 \r
534         hr = srq->handle->Query(&max_wr, &max_sge, &srq_limit);\r
535         if (FAILED(hr)) {\r
536                 return hr;\r
537         }\r
538 \r
539         srq_attr->max_wr = (uint32_t) max_wr;\r
540         srq_attr->max_sge = (uint32_t) max_sge;\r
541         srq_attr->srq_limit = (uint32_t) srq_limit;\r
542         return 0;\r
543 }\r
544 \r
545 __declspec(dllexport)\r
546 int ibv_destroy_srq(struct ibv_srq *srq)\r
547 {\r
548         srq->handle->Release();\r
549         delete srq;\r
550         return 0;\r
551 }\r
552 \r
553 __declspec(dllexport)\r
554 struct ibv_qp *ibv_create_qp(struct ibv_pd *pd,\r
555                                                          struct ibv_qp_init_attr *qp_init_attr)\r
556 {\r
557         WV_QP_CREATE create;\r
558         ibv_qp_attr attr;\r
559         struct ibv_qp *qp;\r
560         HRESULT hr;\r
561 \r
562         qp = new struct ibv_qp;\r
563         if (qp == NULL) {\r
564                 return NULL;\r
565         }\r
566 \r
567         create.pSendCq = qp_init_attr->send_cq->handle;\r
568         create.pReceiveCq = qp_init_attr->recv_cq->handle;\r
569         create.pSharedReceiveQueue = (qp_init_attr->srq != NULL) ?\r
570                                                                  qp_init_attr->srq->handle : NULL;\r
571         create.Context = qp;\r
572         create.SendDepth = qp_init_attr->cap.max_send_wr;\r
573         create.SendSge = qp_init_attr->cap.max_send_sge;\r
574         create.ReceiveDepth = qp_init_attr->cap.max_recv_wr;\r
575         create.ReceiveSge = qp_init_attr->cap.max_recv_sge;\r
576         create.MaxInlineSend = qp_init_attr->cap.max_inline_data;\r
577         create.InitiatorDepth = 0;\r
578         create.ResponderResources = 0;\r
579         create.QpType = (WV_QP_TYPE) qp_init_attr->qp_type;\r
580         create.QpFlags = qp_init_attr->sq_sig_all ? WV_QP_SIGNAL_SENDS : 0;\r
581 \r
582         if (qp_init_attr->qp_type == IBV_QPT_UD) {\r
583                 hr = pd->handle->CreateDatagramQueuePair(&create, &qp->ud_handle);\r
584         } else {\r
585                 hr = pd->handle->CreateConnectQueuePair(&create, &qp->conn_handle);\r
586         }\r
587         if (FAILED(hr)) {\r
588                 goto err;\r
589         }\r
590 \r
591         if (qp_init_attr->qp_type == IBV_QPT_UD) {\r
592                 qp->ud_handle->QueryInterface(IID_IWVQueuePair, (LPVOID *) &qp->handle);\r
593         } else {\r
594                 qp->conn_handle->QueryInterface(IID_IWVQueuePair, (LPVOID *) &qp->handle);\r
595         }\r
596 \r
597         qp->context = pd->context;\r
598         qp->qp_context = qp_init_attr->qp_context;\r
599         qp->pd = pd;\r
600         qp->send_cq = qp_init_attr->send_cq;\r
601         qp->recv_cq = qp_init_attr->recv_cq;\r
602         qp->srq = qp_init_attr->srq;\r
603         qp->state = IBV_QPS_RESET;\r
604         /* qp_num set by ibv_query_qp */\r
605         qp->qp_type = qp_init_attr->qp_type;\r
606 \r
607         hr = ibv_query_qp(qp, &attr, (enum ibv_qp_attr_mask) 0xFFFFFFFF, qp_init_attr);\r
608         if (FAILED(hr)) {\r
609                 goto err;\r
610         }\r
611 \r
612         return qp;\r
613 \r
614 err:\r
615         delete qp;\r
616         return NULL;\r
617 }\r
618 \r
619 __declspec(dllexport)\r
620 int ibv_query_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr,\r
621                                  enum ibv_qp_attr_mask attr_mask,\r
622                                  struct ibv_qp_init_attr *init_attr)\r
623 {\r
624         WV_QP_ATTRIBUTES wv_attr;\r
625         HRESULT hr;\r
626 \r
627         hr = qp->handle->Query(&wv_attr);\r
628         if (FAILED(hr)) {\r
629                 return hr;\r
630         }\r
631 \r
632         /* ibv_qp exposes qp_num.  Save qp_num from query. */\r
633         qp->qp_num = ntohl(wv_attr.Qpn);\r
634 \r
635         init_attr->qp_context = qp->context;\r
636         init_attr->send_cq = qp->send_cq;\r
637         init_attr->recv_cq = qp->recv_cq;\r
638         init_attr->srq = qp->srq;\r
639         init_attr->cap.max_send_wr = (uint32_t) wv_attr.SendDepth;\r
640         init_attr->cap.max_recv_wr = (uint32_t) wv_attr.ReceiveDepth;\r
641         init_attr->cap.max_send_sge = (uint32_t) wv_attr.SendSge;\r
642         init_attr->cap.max_recv_sge = (uint32_t) wv_attr.ReceiveSge;\r
643         init_attr->cap.max_inline_data = (uint32_t) wv_attr.MaxInlineSend;\r
644         init_attr->qp_type = (enum ibv_qp_type) wv_attr.QpType;\r
645         init_attr->sq_sig_all = wv_attr.QpFlags & WV_QP_SIGNAL_SENDS;\r
646 \r
647         attr->qp_state = (enum ibv_qp_state) wv_attr.QpState;\r
648         attr->cur_qp_state = (enum ibv_qp_state) wv_attr.CurrentQpState;\r
649         attr->path_mtu = ibv_convert_mtu(wv_attr.PathMtu);\r
650         attr->path_mig_state = (enum ibv_mig_state) wv_attr.ApmState;\r
651         attr->qkey = ntohl(wv_attr.Qkey);\r
652         attr->rq_psn = ntohl(wv_attr.ReceivePsn);\r
653         attr->sq_psn = ntohl(wv_attr.SendPsn);\r
654         attr->dest_qp_num = ntohl(wv_attr.DestinationQpn);\r
655         attr->qp_access_flags = wv_attr.AccessFlags;\r
656         attr->cap = init_attr->cap;\r
657         ibv_convert_av(qp->context, &attr->ah_attr, &wv_attr.AddressVector);\r
658         if (wv_attr.AlternateAddressVector.DLid != 0) {\r
659                 ibv_convert_av(qp->context, &attr->alt_ah_attr, &wv_attr.AlternateAddressVector);\r
660         }\r
661         attr->pkey_index = wv_attr.PkeyIndex;\r
662         attr->alt_pkey_index = wv_attr.AlternatePkeyIndex;\r
663         attr->en_sqd_async_notify = 0;\r
664         attr->sq_draining = 0;\r
665         attr->max_rd_atomic = (uint8_t) wv_attr.InitiatorDepth;\r
666         attr->max_dest_rd_atomic = (uint8_t) wv_attr.ResponderResources;\r
667         attr->min_rnr_timer = wv_attr.RnrNakTimeout;\r
668         attr->port_num = wv_attr.AddressVector.PortNumber;\r
669         attr->timeout = wv_attr.LocalAckTimeout;\r
670         attr->retry_cnt = wv_attr.SequenceErrorRetryCount;\r
671         attr->rnr_retry = wv_attr.RnrRetryCount;\r
672         attr->alt_port_num = wv_attr.AlternateAddressVector.PortNumber;\r
673         attr->alt_timeout = wv_attr.AlternateLocalAckTimeout;\r
674 \r
675         return 0;\r
676 }\r
677 \r
678 __declspec(dllexport)\r
679 int ibv_modify_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr,\r
680                                   enum ibv_qp_attr_mask attr_mask)\r
681 {\r
682         WV_QP_ATTRIBUTES wv_attr;\r
683         HRESULT hr;\r
684 \r
685         wv_attr.SendDepth = attr->cap.max_send_wr;\r
686         wv_attr.SendSge = attr->cap.max_send_sge;\r
687         wv_attr.ReceiveDepth = attr->cap.max_recv_wr;\r
688         wv_attr.ReceiveSge = attr->cap.max_recv_sge;\r
689         wv_attr.MaxInlineSend = attr->cap.max_inline_data;\r
690         wv_attr.InitiatorDepth = attr->max_rd_atomic;\r
691         wv_attr.ResponderResources = attr->max_dest_rd_atomic;\r
692 \r
693         wv_attr.CurrentQpState = (WV_QP_STATE) attr->cur_qp_state;\r
694         wv_attr.QpState = (WV_QP_STATE) attr->qp_state;\r
695         wv_attr.ApmState = (WV_APM_STATE) attr->path_mig_state;\r
696         wv_attr.DestinationQpn = htonl(attr->dest_qp_num);\r
697         wv_attr.Qkey = htonl(attr->qkey);\r
698         wv_attr.SendPsn = htonl(attr->sq_psn);\r
699         wv_attr.ReceivePsn = htonl(attr->rq_psn);\r
700 \r
701         wv_attr.AccessFlags = attr->qp_access_flags;\r
702         wv_attr.QpFlags = 0;\r
703 \r
704         ibv_convert_ah_attr(qp->context, &wv_attr.AddressVector, &attr->ah_attr);\r
705         wv_attr.AddressVector.PortNumber = attr->port_num;\r
706         wv_attr.PathMtu = 0x80 << attr->path_mtu;\r
707         wv_attr.PkeyIndex = attr->pkey_index;\r
708         wv_attr.LocalAckTimeout = attr->timeout;\r
709 \r
710         if (attr_mask & IBV_QP_ALT_PATH) {\r
711                 ibv_convert_ah_attr(qp->context, &wv_attr.AlternateAddressVector,\r
712                                                         &attr->alt_ah_attr);\r
713                 wv_attr.AlternateAddressVector.PortNumber = attr->alt_port_num;\r
714                 wv_attr.AlternatePathMtu = 0x80 << attr->path_mtu;\r
715                 wv_attr.AlternatePkeyIndex = attr->alt_pkey_index;\r
716                 wv_attr.AlternateLocalAckTimeout = attr->alt_timeout;\r
717         }\r
718 \r
719         wv_attr.RnrNakTimeout = attr->min_rnr_timer;\r
720         wv_attr.SequenceErrorRetryCount = attr->retry_cnt;\r
721         wv_attr.RnrRetryCount = attr->rnr_retry;\r
722 \r
723         hr = qp->handle->Modify(&wv_attr, attr_mask, NULL);\r
724         if (SUCCEEDED(hr) && (attr_mask & IBV_QP_STATE)) {\r
725                 qp->state = attr->qp_state;\r
726         }\r
727 \r
728         return hr;\r
729 }\r
730 \r
731 __declspec(dllexport)\r
732 int ibv_post_send(struct ibv_qp *qp, struct ibv_send_wr *wr,\r
733                                   struct ibv_send_wr **bad_wr)\r
734 {\r
735         struct ibv_send_wr *cur_wr;\r
736         HRESULT hr = 0;\r
737         struct ibv_ah *ah;\r
738 \r
739         if ((qp->qp_type == IBV_QPT_UD) && (wr->next != NULL))\r
740                 return WV_NOT_SUPPORTED;\r
741 \r
742         for (cur_wr = wr; cur_wr != NULL; cur_wr = cur_wr->next) {\r
743                 if (qp->qp_type == IBV_QPT_UD) {\r
744                         ah = cur_wr->wr.ud.ah;\r
745                         cur_wr->wr.ud.ah = (struct ibv_ah *) ah->key;\r
746                         cur_wr->wr.ud.remote_qkey = htonl(cur_wr->wr.ud.remote_qkey);\r
747                         cur_wr->wr.ud.remote_qpn = htonl(cur_wr->wr.ud.remote_qpn);\r
748                 }\r
749 \r
750                 if ((cur_wr->opcode & 0x80000000) != 0) {\r
751                         cur_wr->opcode = (ibv_wr_opcode) (cur_wr->opcode & ~0x80000000);\r
752                         cur_wr->send_flags = (ibv_send_flags) (cur_wr->send_flags | WV_SEND_IMMEDIATE);\r
753                 }\r
754 \r
755                 if (cur_wr->opcode != 0) {\r
756                         cur_wr->wr.rdma.remote_addr = htonll(cur_wr->wr.rdma.remote_addr);\r
757                         cur_wr->wr.rdma.rkey = htonl(cur_wr->wr.rdma.rkey);\r
758                 }\r
759         }\r
760 \r
761         hr = qp->handle->PostSend((WV_SEND_REQUEST *) wr, (WV_SEND_REQUEST **) bad_wr);\r
762 \r
763         for (cur_wr = wr; cur_wr != NULL; cur_wr = cur_wr->next) {\r
764                 if (cur_wr->opcode != 0) {\r
765                         cur_wr->wr.rdma.rkey = ntohl(cur_wr->wr.rdma.rkey);\r
766                         cur_wr->wr.rdma.remote_addr = htonll(cur_wr->wr.rdma.remote_addr);\r
767                 }\r
768 \r
769                 if ((cur_wr->send_flags & WV_SEND_IMMEDIATE) != 0) {\r
770                         cur_wr->send_flags = (ibv_send_flags) (cur_wr->send_flags & ~WV_SEND_IMMEDIATE);\r
771                         cur_wr->opcode = (ibv_wr_opcode) (cur_wr->opcode | 0x80000000);\r
772                 }\r
773 \r
774                 if (qp->qp_type == IBV_QPT_UD) {\r
775                         cur_wr->wr.ud.ah = ah;\r
776                         cur_wr->wr.ud.remote_qkey = ntohl(cur_wr->wr.ud.remote_qkey);\r
777                         cur_wr->wr.ud.remote_qpn = ntohl(cur_wr->wr.ud.remote_qpn);\r
778                 }\r
779         }\r
780 \r
781         return hr;\r
782 }\r
783 \r
784 __declspec(dllexport)\r
785 int ibv_post_recv(struct ibv_qp *qp, struct ibv_recv_wr *wr,\r
786                                   struct ibv_recv_wr **bad_wr)\r
787 {\r
788         HRESULT hr = 0;\r
789 \r
790         for (*bad_wr = wr; *bad_wr != NULL && SUCCEEDED(hr); *bad_wr = (*bad_wr)->next) {\r
791                 hr = qp->handle->PostReceive((*bad_wr)->wr_id, (WV_SGE *) (*bad_wr)->sg_list,\r
792                                                                          (*bad_wr)->num_sge);\r
793         }\r
794         return hr;\r
795 }\r
796 \r
797 __declspec(dllexport)\r
798 int ibv_destroy_qp(struct ibv_qp *qp)\r
799 {\r
800         qp->handle->CancelOverlappedRequests();\r
801         if (qp->qp_type == IBV_QPT_UD) {\r
802                 qp->ud_handle->Release();\r
803         } else {\r
804                 qp->conn_handle->Release();\r
805         }\r
806 \r
807         qp->handle->Release();\r
808         delete qp;\r
809         return 0;\r
810 }\r
811 \r
812 __declspec(dllexport)\r
813 struct ibv_ah *ibv_create_ah(struct ibv_pd *pd, struct ibv_ah_attr *attr)\r
814 {\r
815         WV_ADDRESS_VECTOR av;\r
816         struct ibv_ah *ah;\r
817         HRESULT hr;\r
818 \r
819         ah = new struct ibv_ah;\r
820         if (ah == NULL) {\r
821                 return NULL;\r
822         }\r
823 \r
824         ah->context = pd->context;\r
825         ah->pd = pd;\r
826         ibv_convert_ah_attr(pd->context, &av, attr);\r
827         hr = pd->handle->CreateAddressHandle(&av, &ah->handle, &ah->key);\r
828         if (FAILED(hr)) {\r
829                 delete ah;\r
830                 return NULL;\r
831         }\r
832         return ah;\r
833 }\r
834 \r
835 __declspec(dllexport)\r
836 int ibv_init_ah_from_wc(struct ibv_context *context, uint8_t port_num,\r
837                                                 struct ibv_wc *wc, struct ibv_grh *grh,\r
838                                                 struct ibv_ah_attr *ah_attr)\r
839 {\r
840         uint32_t flow_class;\r
841         int ret;\r
842 \r
843         memset(ah_attr, 0, sizeof *ah_attr);\r
844         ah_attr->dlid = wc->slid;\r
845         ah_attr->sl = wc->sl;\r
846         ah_attr->src_path_bits = wc->dlid_path_bits;\r
847         ah_attr->port_num = port_num;\r
848 \r
849         if (wc->wc_flags & IBV_WC_GRH) {\r
850                 ah_attr->is_global = 1;\r
851                 ah_attr->grh.dgid = grh->sgid;\r
852 \r
853                 ret = ibv_find_gid_index(context, port_num, &grh->dgid);\r
854                 if (ret < 0) {\r
855                         return ret;\r
856                 }\r
857 \r
858                 ah_attr->grh.sgid_index = (uint8_t) ret;\r
859                 flow_class = ntohl(grh->version_tclass_flow);\r
860                 ah_attr->grh.flow_label = flow_class & 0xFFFFF;\r
861                 ah_attr->grh.hop_limit = grh->hop_limit;\r
862                 ah_attr->grh.traffic_class = (flow_class >> 20) & 0xFF;\r
863         }\r
864         return 0;\r
865 }\r
866 \r
867 __declspec(dllexport)\r
868 struct ibv_ah *ibv_create_ah_from_wc(struct ibv_pd *pd, struct ibv_wc *wc,\r
869                                                                          struct ibv_grh *grh, uint8_t port_num)\r
870 {\r
871         struct ibv_ah_attr ah_attr;\r
872         int ret;\r
873 \r
874         ret = ibv_init_ah_from_wc(pd->context, port_num, wc, grh, &ah_attr);\r
875         if (ret != 0) {\r
876                 return NULL;\r
877         }\r
878 \r
879         return ibv_create_ah(pd, &ah_attr);\r
880 }\r
881 \r
882 __declspec(dllexport)\r
883 int ibv_destroy_ah(struct ibv_ah *ah)\r
884 {\r
885         ah->handle->Release();\r
886         delete ah;\r
887         return 0;\r
888 }\r
889 \r
890 __declspec(dllexport)\r
891 int ibv_attach_mcast(struct ibv_qp *qp, union ibv_gid *gid, uint16_t lid)\r
892 {\r
893         return qp->ud_handle->AttachMulticast((WV_GID *) gid, lid, NULL);\r
894 }\r
895 \r
896 __declspec(dllexport)\r
897 int ibv_detach_mcast(struct ibv_qp *qp, union ibv_gid *gid, uint16_t lid)\r
898 {\r
899         return qp->ud_handle->DetachMulticast((WV_GID *) gid, lid, NULL);\r
900 }\r