[VNIC] Initial checkin of VNIC code. Not yet fully functional.
[mirror/winof/.git] / ulp / inic / kernel / vnic_ib.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  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  * $Id$\r
30  */\r
31 #include "vnic_adapter.h"\r
32 #include "vnic_util.h"\r
33 \r
34 #ifndef max_t\r
35 #define max_t(type,x,y) \\r
36         ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })\r
37 #endif\r
38 \r
39 \r
40 static int inicIbInited = 0;\r
41 \r
42 extern struct _vnic_globals g_vnic;\r
43 \r
44 void\r
45 ib_asyncEvent(\r
46                         ib_async_event_rec_t    *pEventRecord );\r
47 \r
48 static void\r
49 _ib_qpCompletion(\r
50         IN              IbQp_t                  *pQp);\r
51 static void\r
52 _ibqp_connect_cb(\r
53         IN              ib_cm_rep_rec_t     *p_cm_rep );\r
54 \r
55 static void\r
56 _ibqp_detach_cb(\r
57         IN              ib_cm_drep_rec_t        *p_drep_rec );\r
58 \r
59 static void\r
60 _ibqp_dreq_cb(\r
61         IN              ib_cm_dreq_rec_t                *p_dreq_rec );\r
62 \r
63 static void\r
64 _ibqp_mra_cb(\r
65         IN              ib_cm_mra_rec_t                 *p_mra_rec );\r
66 \r
67 static void\r
68 _ibqp_rej_cb(\r
69         IN              ib_cm_rej_rec_t         *p_rej_rec );\r
70 static\r
71 void ib_workCompletion(\r
72                 IN                      ib_cq_handle_t  h_cq,\r
73                 IN                      void                    *cqContext );\r
74 \r
75 \r
76 uint8_t\r
77 ibca_findPortNum(\r
78                 struct _viport *p_viport,\r
79                 uint64_t                guid )\r
80 {\r
81         uint8_t port;\r
82 \r
83         for (port = 0; port < p_viport->p_adapter->ca.numPorts; port++ )\r
84         {\r
85                         if (p_viport->p_adapter->ca.portGuids[port] == guid )\r
86                         {\r
87                                 return port+1;\r
88                         }\r
89         }\r
90         return 0;\r
91 }\r
92 \r
93 ib_api_status_t\r
94 ibregion_physInit(\r
95         IN              struct _vnic_adapter*           p_adapter,\r
96         IN              IbRegion_t              *pRegion,\r
97         IN              ib_pd_handle_t  hPd,\r
98         IN              uint64_t                *p_vaddr,\r
99         IN              uint64_t                len )\r
100 {\r
101         ib_phys_create_t        phys_mem;\r
102         ib_phys_range_t         phys_range;\r
103         ib_api_status_t         ib_status = IB_SUCCESS;\r
104         uint64_t                        vaddr = 0;\r
105         VNIC_ENTER ( VNIC_DBG_IB );\r
106 \r
107         UNUSED_PARAM( p_vaddr );\r
108 \r
109         phys_range.base_addr = *(p_vaddr);\r
110         phys_range.size =  len;\r
111         phys_mem.access_ctrl = ( IB_AC_LOCAL_WRITE | IB_AC_RDMA_WRITE );\r
112         phys_mem.buf_offset = 0;\r
113         phys_mem.hca_page_size = PAGE_SIZE;\r
114         phys_mem.length = len;\r
115         phys_mem.num_ranges = 1;\r
116         phys_mem.range_array = &phys_range;\r
117 \r
118         ib_status = p_adapter->ifc.reg_phys( hPd,\r
119                                                                         &phys_mem,\r
120                                                                         &vaddr,\r
121                                                                         &pRegion->lkey,\r
122                                                                         &pRegion->rkey,\r
123                                                                         &pRegion->h_mr );\r
124 \r
125         if ( ib_status != IB_SUCCESS )\r
126         {\r
127                 VNIC_TRACE( VNIC_DBG_ERROR,\r
128                                 ("ib_reg_phys failed status %s(%d)\n",\r
129                                                 p_adapter->ifc.get_err_str(ib_status), ib_status ) );\r
130                 pRegion->h_mr = NULL;\r
131         }\r
132         pRegion->virtAddress = vaddr;\r
133         pRegion->len = len;\r
134 \r
135         VNIC_EXIT( VNIC_DBG_IB );\r
136         return ib_status;\r
137 }\r
138 \r
139 ib_api_status_t\r
140 ibregion_init (\r
141         IN              viport_t                *p_viport,\r
142         IN      OUT     IbRegion_t              *pRegion,\r
143         IN              ib_pd_handle_t  hPd,\r
144         IN              void* __ptr64   vaddr,\r
145         IN              uint64_t                len,\r
146         IN              ib_access_t             access_ctrl )\r
147 {\r
148         ib_api_status_t ib_status;\r
149         ib_mr_create_t  create_mem;\r
150 \r
151         VNIC_ENTER ( VNIC_DBG_IB );\r
152 \r
153         create_mem.length  = len;\r
154         create_mem.vaddr  = vaddr;\r
155         create_mem.access_ctrl = access_ctrl;\r
156 \r
157         ib_status = p_viport->p_adapter->ifc.reg_mem( hPd,\r
158                                                                         &create_mem,\r
159                                                                         &pRegion->lkey,\r
160                                                                         &pRegion->rkey,\r
161                                                                         &pRegion->h_mr );\r
162         if ( ib_status != IB_SUCCESS )\r
163         {\r
164                 VNIC_TRACE( VNIC_DBG_ERROR,\r
165                         ("ib_reg_mem failed status %s(%d)\n",\r
166                         p_viport->p_adapter->ifc.get_err_str( ib_status ), ib_status ));\r
167                 pRegion->h_mr = NULL;\r
168         }\r
169         else\r
170         {\r
171                 pRegion->len = len;\r
172                 pRegion->virtAddress = (uint64_t)( vaddr );\r
173         }\r
174         VNIC_EXIT ( VNIC_DBG_IB );\r
175         return ib_status;\r
176 }\r
177 \r
178 void\r
179 ibregion_cleanup(\r
180                 IN              viport_t        *p_viport,\r
181                 IN              IbRegion_t      *pRegion )\r
182 {\r
183         void    *mr_handle;\r
184         ib_api_status_t ib_status;\r
185 \r
186         VNIC_ENTER( VNIC_DBG_IB );\r
187 \r
188         if( ( mr_handle = InterlockedExchangePointer( (void *)&pRegion->h_mr, NULL )) != NULL )\r
189         {\r
190                 ib_status = p_viport->p_adapter->ifc.dereg_mr( (ib_mr_handle_t)mr_handle );\r
191                 if ( ib_status != IB_SUCCESS )\r
192                 {\r
193                         VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
194                         ("Dereg MR failed status %s(%d)\n",\r
195                                                 p_viport->p_adapter->ifc.get_err_str(ib_status), ib_status ) );\r
196                         return;\r
197                 }\r
198         }\r
199 \r
200         VNIC_EXIT( VNIC_DBG_IB );\r
201 }\r
202 \r
203 \r
204 void\r
205 ibqp_construct(\r
206         IN      OUT             IbQp_t                  *pQp,\r
207         IN                      viport_t                *pViport )\r
208 {\r
209         VNIC_ENTER ( VNIC_DBG_IB );\r
210 \r
211         ASSERT( pQp->qpState == IB_UNINITTED );\r
212 \r
213         pQp->qp      = NULL;\r
214         pQp->cq      = NULL;\r
215         pQp->pViport = pViport;\r
216         pQp->pCa     = &pViport->p_adapter->ca;\r
217 \r
218         NdisAllocateSpinLock( &pQp->qpLock );\r
219 \r
220         InitializeListHead( &pQp->listPtrs);\r
221 }\r
222 \r
223 \r
224 ib_api_status_t\r
225 ibqp_init(\r
226         IN      OUT             IbQp_t                  *pQp,\r
227         IN                      uint64_t                guid,\r
228         IN                      IbConfig_t              *p_conf )\r
229 {\r
230         ib_qp_create_t          attribCreate;\r
231         ib_qp_mod_t                     attribMod;\r
232         ib_qp_attr_t            qpAttribs;\r
233 \r
234         ib_cq_create_t          cq_create;\r
235         ib_cq_handle_t          h_cq;\r
236 \r
237         ib_api_status_t         ib_status = IB_SUCCESS;\r
238 \r
239         VNIC_ENTER ( VNIC_DBG_IB );\r
240 \r
241         if (pQp->qpState != IB_UNINITTED && pQp->qpState != IB_DETACHED )\r
242         {\r
243                 VNIC_TRACE( VNIC_DBG_ERROR,\r
244                         ("ibqp_init: out of state (%d)\n",      pQp->qpState) );\r
245                 return IB_ERROR;\r
246         }\r
247 \r
248         InterlockedExchange( &pQp->qpState, IB_UNINITTED );\r
249 \r
250         pQp->p_conf = p_conf;\r
251 \r
252         cq_create.size = p_conf->numSends + p_conf->numRecvs;\r
253         cq_create.pfn_comp_cb = ib_workCompletion;\r
254         cq_create.h_wait_obj = NULL;\r
255 \r
256         ib_status = pQp->pViport->p_adapter->ifc.create_cq(\r
257                 pQp->pViport->p_adapter->h_ca, &cq_create, pQp, NULL, &h_cq );\r
258 \r
259         if( ib_status != IB_SUCCESS )\r
260         {\r
261                 VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
262                         ("Failed allocating completion queue\n") );\r
263                 goto err1;\r
264         }\r
265 \r
266         pQp->cq = h_cq;\r
267 \r
268         cl_memclr( &attribCreate, sizeof(attribCreate) );\r
269 \r
270         attribCreate.qp_type = IB_QPT_RELIABLE_CONN;\r
271         attribCreate.sq_depth = p_conf->numSends;\r
272         attribCreate.rq_depth = p_conf->numRecvs;\r
273         attribCreate.sq_sge = p_conf->sendGather;\r
274         attribCreate.rq_sge = p_conf->recvScatter;\r
275         attribCreate.h_sq_cq = pQp->cq;\r
276         attribCreate.h_rq_cq = pQp->cq;\r
277         attribCreate.sq_signaled = FALSE;\r
278 \r
279         ib_status = pQp->pViport->p_adapter->ifc.create_qp(\r
280                 pQp->pViport->p_adapter->ca.hPd, &attribCreate, pQp, NULL, &pQp->qp );\r
281         if( ib_status != IB_SUCCESS )\r
282         {\r
283                 VNIC_TRACE_EXIT( VNIC_DBG_IB, ("Create QP failed %s\n",\r
284                         pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) );\r
285                 goto err2;\r
286         }\r
287         ib_status = pQp->pViport->p_adapter->ifc.query_qp(pQp->qp, &qpAttribs);\r
288         if( ib_status != IB_SUCCESS )\r
289         {\r
290                 VNIC_TRACE( VNIC_DBG_ERROR, ("Query QP failed %s\n",\r
291                         pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) );\r
292                 goto err3;\r
293         }\r
294         pQp->qpNumber = qpAttribs.num;\r
295         pQp->portGuid = guid;\r
296         cl_memclr( &attribMod, sizeof(attribMod) );\r
297 \r
298         attribMod.req_state = IB_QPS_INIT;\r
299         attribMod.state.init.primary_port = ibca_findPortNum( pQp->pViport, guid );\r
300         attribMod.state.init.pkey_index = 0;\r
301         attribMod.state.init.access_ctrl = IB_AC_LOCAL_WRITE;\r
302         attribMod.state.init.access_ctrl |= (p_conf->sendGather > 1) ? IB_AC_RDMA_WRITE : 0;\r
303 \r
304         ib_status = pQp->pViport->p_adapter->ifc.modify_qp( pQp->qp, &attribMod );\r
305         if( ib_status != IB_SUCCESS )\r
306         {\r
307                 VNIC_TRACE_EXIT( VNIC_DBG_IB, ("Init QP failed %s\n",\r
308                         pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) );\r
309 \r
310 err3:\r
311                 pQp->pViport->p_adapter->ifc.destroy_qp( pQp->qp, NULL );\r
312 err2:\r
313                 pQp->pViport->p_adapter->ifc.destroy_cq( pQp->cq, NULL );\r
314         }\r
315         else\r
316         {\r
317                 InterlockedExchange( &pQp->qpState, IB_INITTED );\r
318         }\r
319 \r
320 err1:\r
321         VNIC_EXIT ( VNIC_DBG_IB );\r
322         return ib_status;\r
323 }\r
324 \r
325 \r
326 ib_api_status_t\r
327 ibqp_connect(\r
328         IN              IbQp_t   *pQp)\r
329 {\r
330         IbCa_t          *pCa;\r
331         viport_t                *p_viport;\r
332         IbConfig_t      *p_conf;\r
333         ib_api_status_t  ib_status = IB_SUCCESS;\r
334         ib_cm_req_t                     conn_req;\r
335 \r
336         VNIC_ENTER( VNIC_DBG_IB );\r
337 \r
338         if ( pQp->qpState != IB_INITTED )\r
339         {\r
340                 VNIC_TRACE_EXIT( VNIC_DBG_IB,\r
341                         ("ibqp_connect: out of state (%d)\n",pQp->qpState) );\r
342                 return IB_INVALID_STATE;\r
343         }\r
344 \r
345         p_viport = pQp->pViport;\r
346         pCa = pQp->pCa;\r
347         p_conf = pQp->p_conf;\r
348 \r
349 #ifdef VNIC_STATISTIC\r
350         pQp->statistics.connectionTime = cl_get_time_stamp();\r
351 #endif\r
352 \r
353         cl_memclr( &conn_req, sizeof(conn_req));\r
354 \r
355         conn_req.h_al                   = p_viport->p_adapter->h_al;\r
356         conn_req.qp_type                = IB_QPT_RELIABLE_CONN;\r
357         conn_req.h_qp                   = pQp->qp;\r
358         conn_req.p_req_pdata    = (uint8_t*)&pQp->p_conf->connData;\r
359         conn_req.req_length             = sizeof( Inic_ConnectionData_t );\r
360         conn_req.svc_id                 = pQp->p_conf->sid;\r
361         conn_req.pkey                   = pQp->p_conf->pathInfo.pkey;\r
362 \r
363         conn_req.p_primary_path = &pQp->p_conf->pathInfo;\r
364 \r
365         conn_req.retry_cnt              = (uint8_t)pQp->p_conf->retryCount;\r
366         conn_req.rnr_nak_timeout = pQp->p_conf->minRnrTimer;\r
367         conn_req.rnr_retry_cnt  = (uint8_t)pQp->p_conf->rnrRetryCount;\r
368         conn_req.max_cm_retries = 5;\r
369         conn_req.remote_resp_timeout = ib_path_rec_pkt_life( &pQp->p_conf->pathInfo ) + 1;\r
370         conn_req.local_resp_timeout  = ib_path_rec_pkt_life( &pQp->p_conf->pathInfo ) + 1;\r
371 \r
372         conn_req.compare_length =       0;\r
373         conn_req.resp_res               =       0;\r
374 \r
375         conn_req.flow_ctrl              =       TRUE;\r
376         \r
377         conn_req.pfn_cm_req_cb  =       NULL;\r
378         conn_req.pfn_cm_rep_cb  =       _ibqp_connect_cb;\r
379         conn_req.pfn_cm_mra_cb  =       _ibqp_mra_cb;\r
380         conn_req.pfn_cm_rej_cb  =       _ibqp_rej_cb;\r
381 \r
382         InterlockedExchange( &pQp->qpState, IB_ATTACHING );\r
383 \r
384         ib_status = p_viport->p_adapter->ifc.cm_req ( &conn_req );\r
385         if ( ib_status != IB_SUCCESS && ib_status != IB_PENDING )\r
386         {\r
387                 VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
388                         ("Connect request return status %s\n",\r
389                         p_viport->p_adapter->ifc.get_err_str( ib_status )) );\r
390                 InterlockedExchange( &pQp->qpState, IB_DETACHED );\r
391                 return ib_status;\r
392         }\r
393 \r
394         if( cl_event_wait_on(\r
395                 &p_viport->conn_event, EVENT_NO_TIMEOUT, FALSE ) != CL_SUCCESS )\r
396         {\r
397                 VNIC_TRACE_EXIT( VNIC_DBG_ERROR, ("conn event timeout!\n") );\r
398                 return IB_TIMEOUT;\r
399         }\r
400 \r
401         if( pQp->qpState != IB_ATTACHED )\r
402         {\r
403                 VNIC_TRACE( VNIC_DBG_ERROR, ("QP connect failed\n") );\r
404                 ib_status = IB_ERROR;\r
405         }\r
406 \r
407         VNIC_EXIT( VNIC_DBG_IB );\r
408         return ib_status;\r
409 }\r
410 \r
411 \r
412 static void\r
413 _ibqp_detach_cb(\r
414                 IN              ib_cm_drep_rec_t        *p_drep_rec )\r
415 {\r
416         IbQp_t  *pQp = (IbQp_t * __ptr64 )p_drep_rec->qp_context;\r
417         VNIC_ENTER( VNIC_DBG_IB );\r
418         CL_ASSERT( p_drep_rec );\r
419 \r
420         InterlockedExchange( &pQp->qpState, IB_DETACHED );\r
421 \r
422         VNIC_EXIT( VNIC_DBG_IB );\r
423 }\r
424 \r
425 static void\r
426 _ibqp_rej_cb(\r
427          IN             ib_cm_rej_rec_t         *p_rej_rec )\r
428 {\r
429         IbQp_t  *pQp = (IbQp_t * __ptr64 )p_rej_rec->qp_context;\r
430         CL_ASSERT(p_rej_rec );\r
431 \r
432         InterlockedExchange( &pQp->qpState, IB_DETACHED );\r
433         switch ( p_rej_rec->rej_status )\r
434         {\r
435                 case IB_REJ_USER_DEFINED:\r
436                 \r
437                         VNIC_TRACE ( VNIC_DBG_IB | VNIC_DBG_ERROR,\r
438                                 ("Conn req user reject status %d\nARI: %s\n",\r
439                                                 cl_ntoh16( p_rej_rec->rej_status ),\r
440                                                 p_rej_rec->p_ari ));\r
441                         break;\r
442                 default:\r
443                         VNIC_TRACE( VNIC_DBG_IB | VNIC_DBG_ERROR,\r
444                                 ("Conn req reject status %d\n",\r
445                                                 cl_ntoh16( p_rej_rec->rej_status )) );\r
446         }\r
447         viport_failure( pQp->pViport );\r
448         cl_event_signal( &pQp->pViport->conn_event );\r
449 }\r
450 \r
451 static void\r
452 _ibqp_mra_cb(\r
453          IN             ib_cm_mra_rec_t                 *p_mra_rec )\r
454 {\r
455         VNIC_ENTER( VNIC_DBG_IB );\r
456         CL_ASSERT( p_mra_rec );\r
457         UNREFERENCED_PARAMETER( p_mra_rec );\r
458         VNIC_EXIT( VNIC_DBG_IB );\r
459 }\r
460 \r
461 static void\r
462 _ibqp_dreq_cb(\r
463           IN    ib_cm_dreq_rec_t                *p_dreq_rec )\r
464 {\r
465         ib_api_status_t ib_status = IB_SUCCESS;\r
466         ib_cm_drep_t    cm_drep;\r
467         IbQp_t  *pQp    = (IbQp_t * __ptr64 )p_dreq_rec->qp_context;\r
468 \r
469         VNIC_ENTER( VNIC_DBG_IB );\r
470         CL_ASSERT( p_dreq_rec );\r
471 \r
472         cm_drep.drep_length = 0;\r
473         cm_drep.p_drep_pdata = NULL;\r
474 \r
475         ib_status = pQp->pViport->p_adapter->ifc.cm_drep(\r
476                 p_dreq_rec->h_cm_dreq, &cm_drep );\r
477         if ( ib_status != IB_SUCCESS )\r
478         {\r
479                 VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
480                         ("dreq_cb failed status %s(%d)\n",\r
481                         pQp->pViport->p_adapter->ifc.get_err_str( ib_status ), ib_status));\r
482                 return;\r
483         }\r
484 \r
485         InterlockedExchange (&pQp->qpState,  IB_DETACHED );\r
486 \r
487         VNIC_EXIT( VNIC_DBG_IB );\r
488 }\r
489 \r
490 void\r
491 ibqp_detach(\r
492                 IN                      IbQp_t          *pQp )\r
493 {\r
494         ib_cm_dreq_t    cm_dreq;\r
495         ib_api_status_t         ib_status = IB_SUCCESS;\r
496 \r
497         VNIC_ENTER( VNIC_DBG_IB );\r
498 \r
499         NdisAcquireSpinLock( &pQp->qpLock );\r
500 \r
501         if( pQp->qpState == IB_ATTACHED )\r
502         {\r
503                 InterlockedExchange ( &pQp->qpState, IB_DETACHING );\r
504 \r
505                 cm_dreq.h_qp = pQp->qp;\r
506                 cm_dreq.qp_type = IB_QPT_RELIABLE_CONN;\r
507                 cm_dreq.p_dreq_pdata = NULL;\r
508                 cm_dreq.dreq_length = 0;\r
509                 cm_dreq.pfn_cm_drep_cb = _ibqp_detach_cb;\r
510                 ib_status = pQp->pViport->p_adapter->ifc.cm_dreq( &cm_dreq );\r
511                 if ( ib_status != IB_SUCCESS )\r
512                 {\r
513                         VNIC_TRACE( VNIC_DBG_ERROR,\r
514                                 (" cm_dreq failed status %s\n",\r
515                                 pQp->pViport->p_adapter->ifc.get_err_str( ib_status )));\r
516                 }\r
517                 ib_status = pQp->pViport->p_adapter->ifc.destroy_qp( pQp->qp, NULL );\r
518         }\r
519         NdisReleaseSpinLock( &pQp->qpLock );\r
520 \r
521         VNIC_EXIT( VNIC_DBG_IB );\r
522         return;\r
523 }\r
524 \r
525 void\r
526 ibqp_cleanup(\r
527                 IN              IbQp_t          *pQp )\r
528 {\r
529         ib_api_status_t         ib_status = IB_SUCCESS;\r
530         LONG                            qp_state;\r
531 \r
532         VNIC_ENTER( VNIC_DBG_IB );\r
533 \r
534         qp_state = InterlockedExchange( &pQp->qpState, IB_UNINITTED );\r
535         if ( qp_state != IB_UNINITTED &&\r
536                  qp_state != IB_DETACHED &&\r
537                  qp_state != IB_DETACHING )\r
538         {\r
539                 ib_status = pQp->pViport->p_adapter->ifc.destroy_qp( pQp->qp, NULL );\r
540                 if ( ib_status != IB_SUCCESS )\r
541                 {\r
542                         VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
543                                 ("destroy_qp failed status %s\n",\r
544                                 pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) );\r
545                 }\r
546         }\r
547 \r
548         VNIC_EXIT( VNIC_DBG_IB );\r
549         return;\r
550 }\r
551 \r
552 ib_api_status_t ibqp_postSend(IbQp_t *pQp, Io_t *pIo)\r
553 {\r
554         ib_api_status_t       ib_status;\r
555 \r
556 #ifdef VNIC_STATISTIC\r
557         int64_t         postTime;\r
558 #endif /* VNIC_STATISTIC */\r
559 \r
560         VNIC_ENTER( VNIC_DBG_IB );\r
561 \r
562         NdisAcquireSpinLock( &pQp->qpLock );\r
563 \r
564         if( pQp->qpState != IB_ATTACHED )\r
565         {\r
566                 ib_status = IB_INVALID_STATE;\r
567                 goto failure;\r
568         }\r
569 \r
570 #ifdef VNIC_STATISTIC\r
571         pIo->time = postTime = cl_get_time_stamp();\r
572 #endif /* VNIC_STATISTIC */\r
573         if (pIo->wrq.wr_type == WR_RDMA_WRITE )\r
574                 pIo->type = RDMA;\r
575         else\r
576                 pIo->type = SEND;\r
577 \r
578         ib_status =\r
579                 pQp->pViport->p_adapter->ifc.post_send( pQp->qp, &pIo->wrq, NULL );\r
580 \r
581 #ifdef VNIC_STATISTIC\r
582         postTime = cl_get_time_stamp() - postTime;\r
583 #endif /* VNIC_STATISTIC */\r
584 \r
585         if( ib_status != IB_SUCCESS )\r
586         {\r
587                 VNIC_TRACE( VNIC_DBG_ERROR, ("ib_post_send returned %s\n",\r
588                         pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) );\r
589         }\r
590         else\r
591         {\r
592 #ifdef VNIC_STATISTIC\r
593                 if (pIo->wrq.wr_type == WR_RDMA_WRITE)\r
594                 {\r
595                         pQp->statistics.rdmaPostTime += postTime;\r
596                         pQp->statistics.rdmaPostIos++;\r
597                 }\r
598                 else\r
599                 {\r
600                         pQp->statistics.sendPostTime += postTime;\r
601                         pQp->statistics.sendPostIos++;\r
602                 }\r
603 #endif /* VNIC_STATISTIC */\r
604         }\r
605 \r
606 failure:\r
607         NdisReleaseSpinLock( &pQp->qpLock );\r
608         VNIC_EXIT( VNIC_DBG_IB );\r
609         return ib_status;\r
610 }\r
611 \r
612 \r
613 ib_api_status_t\r
614 ibqp_postRecv(IbQp_t *pQp, Io_t *pIo)\r
615 {\r
616         ib_api_status_t  ib_status = IB_SUCCESS;\r
617 #ifdef VNIC_STATISTIC\r
618         int64_t      postTime;\r
619 #endif /* VNIC_STATISTIC */\r
620 \r
621         NdisAcquireSpinLock( &pQp->qpLock );\r
622         /* can post recvieves before connecting queue pair */\r
623         if( pQp->qpState != IB_INITTED && pQp->qpState != IB_ATTACHED )\r
624         {\r
625                 NdisReleaseSpinLock( &pQp->qpLock );\r
626                 return IB_INVALID_STATE;\r
627         }\r
628         pIo->type = RECV;\r
629 \r
630 #ifdef VNIC_STATISTIC\r
631         postTime = cl_get_time_stamp();\r
632         if (pIo->time != 0)\r
633         {\r
634                 pQp->statistics.recvCompTime += postTime - pIo->time;\r
635                 pQp->statistics.recvCompIos++;\r
636         }\r
637 #endif /* VNIC_STATISTIC */\r
638 \r
639         ib_status =\r
640                 pQp->pViport->p_adapter->ifc.post_recv(pQp->qp, &pIo->r_wrq, NULL );\r
641 \r
642 #ifdef VNIC_STATISTIC\r
643         postTime = (cl_get_time_stamp()) - postTime;\r
644 #endif /* VNIC_STATISTIC */\r
645 \r
646         if( ib_status != IB_SUCCESS )\r
647         {\r
648                 VNIC_TRACE( VNIC_DBG_ERROR,\r
649                         ("Post Recv failed status %s(%d)\n",\r
650                         pQp->pViport->p_adapter->ifc.get_err_str(ib_status), ib_status ));\r
651 \r
652                 NdisReleaseSpinLock( &pQp->qpLock );\r
653                 return FALSE;\r
654         }\r
655         else\r
656         {\r
657 #ifdef VNIC_STATISTIC\r
658                 pQp->statistics.recvPostTime += postTime;\r
659                 pQp->statistics.recvPostIos++;\r
660 #endif /* VNIC_STATISTIC */\r
661         }\r
662 \r
663         NdisReleaseSpinLock( &pQp->qpLock );\r
664         return ib_status;\r
665 }\r
666 \r
667 \r
668 static void\r
669 _ibqp_connect_cb(\r
670         IN  ib_cm_rep_rec_t     *p_cm_rep )\r
671 {\r
672         IbQp_t                          *pQp;\r
673         ib_api_status_t         ib_status = IB_SUCCESS;\r
674 \r
675         union\r
676         {\r
677                 ib_cm_rtu_t                     cm_rtu;\r
678                 ib_cm_mra_t                     cm_mra;\r
679                 ib_cm_rej_t                     cm_rej;\r
680         } u_reply;\r
681 \r
682         viport_t                        *p_viport;\r
683 \r
684         VNIC_ENTER( VNIC_DBG_IB );\r
685 \r
686         pQp = (IbQp_t * __ptr64 )p_cm_rep->qp_context;\r
687         p_viport = pQp->pViport;\r
688 \r
689         ASSERT( pQp->qpState == IB_ATTACHING );\r
690 \r
691         ib_status = p_viport->p_adapter->ifc.rearm_cq( pQp->cq, FALSE );\r
692         if ( ib_status != IB_SUCCESS )\r
693         {\r
694                 VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
695                                         ("Rearm CQ failed %s\n",\r
696                                         p_viport->p_adapter->ifc.get_err_str( ib_status )) );\r
697 \r
698                 cl_memclr( &u_reply.cm_rej, sizeof( u_reply.cm_rej ) );\r
699                 u_reply.cm_rej.rej_status = IB_REJ_INSUF_RESOURCES;\r
700 \r
701                 p_viport->p_adapter->ifc.cm_rej( p_cm_rep->h_cm_rep, &u_reply.cm_rej );\r
702                 goto err;\r
703         }\r
704 \r
705         cl_memclr( &u_reply.cm_rtu, sizeof( u_reply.cm_rtu ) );\r
706         u_reply.cm_rtu.access_ctrl = IB_AC_LOCAL_WRITE;\r
707 \r
708         if( pQp->p_conf->sendGather > 1 )\r
709                 u_reply.cm_rtu.access_ctrl |= ( IB_AC_RDMA_WRITE );\r
710 \r
711         u_reply.cm_rtu.pfn_cm_dreq_cb = _ibqp_dreq_cb;\r
712 \r
713         ib_status = p_viport->p_adapter->ifc.cm_rtu ( p_cm_rep->h_cm_rep, &u_reply.cm_rtu );\r
714         if ( ib_status != IB_SUCCESS )\r
715         {\r
716                 VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
717                                         ("Send RTU failed\n") );\r
718 err:\r
719                 InterlockedExchange( &pQp->qpState, IB_DETACHED );\r
720                 viport_failure( p_viport );\r
721         }\r
722         else\r
723         {\r
724                 InterlockedExchange ( &pQp->qpState,  IB_ATTACHED );\r
725         }\r
726 \r
727         cl_event_signal( &p_viport->conn_event );\r
728         VNIC_EXIT( VNIC_DBG_IB );\r
729 }\r
730 \r
731 \r
732 #define WC_LIST_SIZE_TO_POLL 4\r
733 static void\r
734 _ib_qpCompletion(\r
735                 IN                      IbQp_t          *pQp )\r
736 {\r
737         Io_t                            *pIo;\r
738         ib_wc_t                         wc[WC_LIST_SIZE_TO_POLL];\r
739         ib_wc_t                         *p_free_wc;\r
740         ib_wc_t                         *p_done_wc;\r
741         ib_api_status_t         ib_status = IB_SUCCESS;\r
742         int                                     i;\r
743 \r
744 #ifdef VNIC_STATISTIC\r
745         int64_t                         compTime;\r
746         uint32_t                        compNum = 0;\r
747 #endif /* VNIC_STATISTIC */\r
748 \r
749         VNIC_ENTER ( VNIC_DBG_IB );\r
750 \r
751         if ( pQp->qpState != IB_ATTACHING && pQp->qpState != IB_ATTACHED )\r
752                 return;\r
753 \r
754 #ifdef VNIC_STATISTIC\r
755         compTime = cl_get_time_stamp();\r
756         pQp->statistics.numCallbacks++;\r
757 #endif /* VNIC_STATISTIC */\r
758 \r
759         for( i = 0; i < (WC_LIST_SIZE_TO_POLL - 1); i++ )\r
760         {\r
761                 wc[i].p_next = &wc[i + 1];\r
762         }\r
763         wc[(WC_LIST_SIZE_TO_POLL - 1)].p_next = NULL;\r
764 \r
765         p_free_wc = wc;\r
766         p_done_wc = NULL;\r
767 \r
768         ib_status = pQp->pViport->p_adapter->ifc.poll_cq( pQp->cq, &p_free_wc, &p_done_wc );\r
769 \r
770         if ( ib_status != IB_SUCCESS && ib_status != IB_NOT_FOUND )\r
771         {\r
772                 VNIC_TRACE ( VNIC_DBG_ERROR,\r
773                         ("ib_poll_cq failed status %d(%s)\n", ib_status,\r
774                                                 pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) );\r
775                 return;\r
776         }\r
777 \r
778         while ( p_done_wc )\r
779         {\r
780                 pIo = (Io_t *)(uintn_t)p_done_wc->wr_id;\r
781 \r
782                 if (pIo)\r
783                 {\r
784                         /* keep completion status for proper ndis packet return status */\r
785                         pIo->wc_status = p_done_wc->status;\r
786 #ifdef VNIC_STATISTIC\r
787                         if (pIo->type == RECV)\r
788                         {\r
789                                 pIo->time = compTime;\r
790                         }\r
791                         else if (pIo->type == RDMA)\r
792                         {\r
793                                 pQp->statistics.rdmaCompTime += compTime - pIo->time;\r
794                                 pQp->statistics.rdmaCompIos++;\r
795                         }\r
796                         else if (pIo->type == SEND)\r
797                         {\r
798                                 pQp->statistics.sendCompTime += compTime - pIo->time;\r
799                                 pQp->statistics.sendCompIos++;\r
800                         }\r
801                         pQp->statistics.numIos++;\r
802                         if ( ++compNum > pQp->statistics.maxIos)\r
803                         {\r
804                                         pQp->statistics.maxIos = compNum;\r
805                         }\r
806 #endif /* VNIC_STATISTIC */\r
807                         VNIC_TRACE( VNIC_DBG_IB,\r
808                                 ("ib_workCompletion: WcType = %d, Status = %d, Length = %d\n",\r
809                                         p_done_wc->wc_type,\r
810                                         p_done_wc->status,\r
811                                         ( p_done_wc->wc_type == IB_WC_RECV )? p_done_wc->length : 0 ) );\r
812 \r
813                         if( pIo->pRoutine )\r
814                         {\r
815                                 (*pIo->pRoutine)( pIo );\r
816                         }\r
817                 }\r
818 \r
819                 if (p_done_wc->status != IB_WCS_SUCCESS )\r
820                 {\r
821                         VNIC_TRACE( VNIC_DBG_IB,\r
822                                         ("Failed completion, type = %d, status = %d (%s)\n",\r
823                                         p_done_wc->wc_type,\r
824                                         p_done_wc->status,\r
825                                         pQp->pViport->p_adapter->ifc.get_wc_status_str (p_done_wc->status) ) );\r
826                 }\r
827 \r
828                 p_done_wc = p_done_wc->p_next;\r
829         }\r
830 \r
831         ib_status = pQp->pViport->p_adapter->ifc.rearm_cq( pQp->cq, FALSE );\r
832 \r
833         if ( ib_status != IB_SUCCESS )\r
834         {\r
835                 VNIC_TRACE( VNIC_DBG_ERROR,\r
836                         ("Rearm CQ failed status %d(%s)\n", ib_status,\r
837                                                 pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) );\r
838         }\r
839         return;\r
840 }\r
841 \r
842 \r
843 static\r
844 void ib_workCompletion(\r
845                 IN                      ib_cq_handle_t  h_cq,\r
846                 IN                      void                    *cqContext )\r
847 {\r
848         IbQp_t           *pQp;\r
849 \r
850         VNIC_ENTER ( VNIC_DBG_IB );\r
851         UNREFERENCED_PARAMETER( h_cq );\r
852         pQp = (IbQp_t *)cqContext;\r
853         _ib_qpCompletion(pQp);\r
854 \r
855         VNIC_EXIT ( VNIC_DBG_IB );\r
856         return;\r
857 }\r
858 \r
859 void\r
860 ib_asyncEvent(\r
861         IN              ib_async_event_rec_t            *pEventRecord )\r
862 {\r
863         IbQp_t   *pQp;\r
864 \r
865         VNIC_ENTER ( VNIC_DBG_IB );\r
866 \r
867         if ( pEventRecord )\r
868         {\r
869                 switch ( pEventRecord->code )\r
870                 {\r
871                         case IB_AE_QP_COMM:\r
872                         case IB_AE_QP_FATAL:\r
873 \r
874                                 pQp = (IbQp_t * __ptr64 )pEventRecord->context;\r
875                                 if (pQp)\r
876                                 {\r
877                                         VNIC_TRACE( VNIC_DBG_ERROR,\r
878                                                 ("Async Event %d  QP State %#x\n",\r
879                                                 pEventRecord->code, pQp->qpState ));\r
880                                 }\r
881                                 break;\r
882                         default:\r
883                                 VNIC_TRACE( VNIC_DBG_ERROR,\r
884                                         ("Async Event %d received\n", pEventRecord->code) );\r
885                                 break;\r
886                 }\r
887         }\r
888         else\r
889         {\r
890                 VNIC_TRACE( VNIC_DBG_ERROR, ("Unknown NULL event\n") );\r
891         }\r
892         VNIC_EXIT ( VNIC_DBG_IB );\r
893 }\r
894 \r
895 \r
896 \r
897 \r
898 \r
899 \r
900 \r