[ipoib 6] Bug fixes to the driver.
[mirror/winof/.git] / ulp / ipoib_NDIS6_CM / kernel / ipoib_port.cpp
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.\r
4  * Portions Copyright (c) 2008 Microsoft 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 AND\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  * $Id: ipoib_port.c 4506 2009-06-23 14:40:54Z xalex $\r
32  */\r
33 \r
34 #include "precompile.h"\r
35 \r
36 #if defined(EVENT_TRACING)\r
37 #ifdef offsetof\r
38 #undef offsetof\r
39 #endif\r
40 #include "ipoib_port.tmh"\r
41 #endif\r
42 #include <offload.h>\r
43 \r
44 #include "wdm.h"\r
45 #include <ntddk.h>\r
46 \r
47 extern ULONG g_ipoib_send;\r
48 extern ULONG g_ipoib_send_ack;\r
49 extern ULONG g_ipoib_send_SW;\r
50 extern ULONG g_ipoib_send_SG;\r
51 extern ULONG g_ipoib_send_SW_in_loop;\r
52 extern ULONG g_ipoib_send_SG_pending;\r
53 extern ULONG g_ipoib_send_SG_real;\r
54 extern ULONG g_ipoib_send_SG_failed;\r
55 \r
56 \r
57 \r
58 \r
59 ib_gid_t        bcast_mgid_template = {\r
60         0xff,                                                           /* multicast field */\r
61         0x12,                                                           /* scope (to be filled in) */\r
62         0x40, 0x1b,                                                     /* IPv4 signature */\r
63         0xff, 0xff,                                                     /* 16 bits of P_Key (to be filled in) */\r
64         0x00, 0x00, 0x00, 0x00, 0x00, 0x00,     /* 48 bits of zeros */\r
65         0xff, 0xff, 0xff, 0xff,                         /* 32 bit IPv4 broadcast address */\r
66 };\r
67 \r
68 \r
69 #ifdef _DEBUG_\r
70 /* Handy pointer for debug use. */\r
71 ipoib_port_t    *gp_ipoib_port;\r
72 #endif\r
73 \r
74 static void __port_mcast_garbage_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2);\r
75 static void __port_do_mcast_garbage(ipoib_port_t* const p_port );\r
76 \r
77 \r
78 static void __recv_cb_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2);\r
79 \r
80 #if 0\r
81 #ifndef _IPOIB_DEBUG_NDIS6\r
82 #define _IPOIB_DEBUG_NDIS6\r
83 CL_INLINE void CL_API\r
84 cl_qlist_check_validity(\r
85         IN      cl_qlist_t* const       p_list )\r
86 {\r
87         cl_list_item_t  *p_item;\r
88         size_t cnt = 0;\r
89 \r
90         /* CL_ASSERT that a non-null pointer is provided. */\r
91         CL_ASSERT( p_list );\r
92         /* CL_ASSERT that the list was initialized. */\r
93         CL_ASSERT( p_list->state == CL_INITIALIZED );\r
94         p_item = cl_qlist_head(p_list);\r
95         while(p_item != cl_qlist_end(p_list)) {\r
96                 ++cnt;\r
97                 CL_ASSERT(p_item->p_list == p_list);\r
98                 p_item = p_item->p_next;\r
99                 CL_ASSERT (cnt <= p_list->count);\r
100         }\r
101         CL_ASSERT (cnt == p_list->count);\r
102         return;\r
103 }\r
104 #endif\r
105 #endif\r
106 /******************************************************************************\r
107 *\r
108 * Declarations\r
109 *\r
110 ******************************************************************************/\r
111 static void\r
112 __port_construct(\r
113         IN                              ipoib_port_t* const                     p_port );\r
114 \r
115 static ib_api_status_t\r
116 __port_init(\r
117         IN                              ipoib_port_t* const                     p_port,\r
118         IN                              ipoib_adapter_t* const          p_adapter,\r
119         IN                              ib_pnp_port_rec_t* const        p_pnp_rec );\r
120 \r
121 static void\r
122 __port_destroying(\r
123         IN                              cl_obj_t* const                         p_obj );\r
124 \r
125 static void\r
126 __port_cleanup(\r
127         IN                              cl_obj_t* const                         p_obj );\r
128 \r
129 static void\r
130 __port_free(\r
131         IN                              cl_obj_t* const                         p_obj );\r
132 \r
133 static ib_api_status_t\r
134 __port_query_ca_attrs( \r
135         IN              ipoib_port_t* const                                     p_port,\r
136         IN              ib_ca_attr_t**                                          pp_ca_attrs );\r
137 \r
138 static void\r
139 __srq_async_event_cb(\r
140 IN                      ib_async_event_rec_t            *p_event_rec );\r
141 \r
142 /******************************************************************************\r
143 *\r
144 * IB resource manager operations\r
145 *\r
146 ******************************************************************************/\r
147 static void\r
148 __ib_mgr_construct(\r
149         IN                              ipoib_port_t* const                     p_port );\r
150 \r
151 static ib_api_status_t\r
152 __ib_mgr_init(\r
153         IN                              ipoib_port_t* const                     p_port );\r
154 \r
155 static void\r
156 __ib_mgr_destroy(\r
157         IN                              ipoib_port_t* const                     p_port );\r
158 \r
159 static void\r
160 __qp_event(\r
161         IN                              ib_async_event_rec_t            *p_event_rec );\r
162 \r
163 static void\r
164 __cq_event(\r
165         IN                              ib_async_event_rec_t            *p_event_rec );\r
166 \r
167 static ib_api_status_t\r
168 __ib_mgr_activate(\r
169         IN                              ipoib_port_t* const                     p_port );\r
170 \r
171 /******************************************************************************\r
172 *\r
173 * Buffer manager operations.\r
174 *\r
175 ******************************************************************************/\r
176 static void\r
177 __buf_mgr_construct(\r
178         IN                              ipoib_port_t* const                     p_port );\r
179 \r
180 static ib_api_status_t\r
181 __buf_mgr_init(\r
182         IN                              ipoib_port_t* const                     p_port );\r
183 \r
184 static void\r
185 __buf_mgr_destroy(\r
186         IN                              ipoib_port_t* const                     p_port );\r
187 \r
188 static cl_status_t\r
189 __recv_ctor(\r
190         IN                              void* const                                     p_object,\r
191         IN                              void*                                           context,\r
192                 OUT                     cl_pool_item_t** const          pp_pool_item );\r
193 \r
194 #if !IPOIB_INLINE_RECV\r
195 static void\r
196 __recv_dtor(\r
197         IN              const   cl_pool_item_t* const           p_pool_item,\r
198         IN                              void                                            *context );\r
199 #endif  /* IPOIB_INLINE_RECV */\r
200 \r
201 static inline ipoib_send_desc_t*\r
202 __buf_mgr_get_send(\r
203         IN                              ipoib_port_t* const                     p_port );\r
204 \r
205 static inline void\r
206 __buf_mgr_put_send(\r
207         IN                              ipoib_port_t* const                     p_port,\r
208         IN                              ipoib_send_desc_t* const        p_desc );\r
209 \r
210 static inline ipoib_recv_desc_t*\r
211 __buf_mgr_get_recv(\r
212         IN                              ipoib_port_t* const                     p_port );\r
213 \r
214 static inline void\r
215 __buf_mgr_put_recv(\r
216         IN                              ipoib_port_t* const                     p_port,\r
217         IN                              ipoib_recv_desc_t* const        p_desc,\r
218         IN                              NET_BUFFER_LIST* const          p_net_buffer_list OPTIONAL );\r
219 \r
220 static inline void\r
221 __buf_mgr_put_recv_list(\r
222         IN                              ipoib_port_t* const                     p_port,\r
223         IN                              cl_qlist_t* const                       p_list );\r
224 \r
225 //NDIS60\r
226 static inline NET_BUFFER_LIST*\r
227 __buf_mgr_get_NBL(\r
228         IN                              ipoib_port_t* const                     p_port,\r
229         IN                              ipoib_recv_desc_t* const        p_desc );\r
230 \r
231 \r
232 /******************************************************************************\r
233 *\r
234 * Receive manager operations.\r
235 *\r
236 ******************************************************************************/\r
237 static void\r
238 __recv_mgr_construct(\r
239         IN                              ipoib_port_t* const                     p_port );\r
240 \r
241 static ib_api_status_t\r
242 __recv_mgr_init(\r
243         IN                              ipoib_port_t* const                     p_port );\r
244 \r
245 static void\r
246 __recv_mgr_destroy(\r
247         IN                              ipoib_port_t* const                     p_port );\r
248 \r
249 /* Posts receive buffers to the receive queue. */\r
250 int32_t\r
251 __recv_mgr_repost(\r
252         IN                              ipoib_port_t* const                     p_port );\r
253 \r
254 static void\r
255 __recv_cb(\r
256         IN              const   ib_cq_handle_t                          h_cq,\r
257         IN                              void                                            *cq_context );\r
258 \r
259 static void\r
260 __recv_get_endpts(\r
261         IN                              ipoib_port_t* const                     p_port,\r
262         IN                              ipoib_recv_desc_t* const        p_desc,\r
263         IN                              ib_wc_t* const                          p_wc,\r
264                 OUT                     ipoib_endpt_t** const           pp_src,\r
265                 OUT                     ipoib_endpt_t** const           pp_dst );\r
266 \r
267 static int32_t\r
268 __recv_mgr_filter(\r
269         IN                              ipoib_port_t* const                     p_port,\r
270         IN                              ib_wc_t* const                          p_done_wc_list,\r
271                 OUT                     cl_qlist_t* const                       p_done_list,\r
272                 OUT                     cl_qlist_t* const                       p_bad_list );\r
273 \r
274 static ib_api_status_t\r
275 __recv_gen(\r
276         IN              const   ipoib_pkt_t* const                      p_ipoib,\r
277                 OUT                     eth_pkt_t* const                        p_eth,\r
278         IN                              ipoib_endpt_t* const            p_src,\r
279         IN                              ipoib_endpt_t* const            p_dst );\r
280 \r
281 static ib_api_status_t\r
282 __recv_dhcp(\r
283         IN                              ipoib_port_t* const                     p_port,\r
284         IN              const   ipoib_pkt_t* const                      p_ipoib,\r
285                 OUT                     eth_pkt_t* const                        p_eth,\r
286         IN                              ipoib_endpt_t* const            p_src,\r
287         IN                              ipoib_endpt_t* const            p_dst );\r
288 \r
289 static ib_api_status_t\r
290 __recv_arp(\r
291         IN                              ipoib_port_t* const                     p_port,\r
292         IN                              ib_wc_t* const                          p_wc,\r
293         IN              const   ipoib_pkt_t* const                      p_ipoib,\r
294                 OUT                     eth_pkt_t* const                        p_eth,\r
295         IN                              ipoib_endpt_t** const           p_src,\r
296         IN                              ipoib_endpt_t* const            p_dst );\r
297 \r
298 static ib_api_status_t\r
299 __recv_mgr_prepare_NBL(\r
300         IN                              ipoib_port_t* const                     p_port,\r
301         IN                              ipoib_recv_desc_t* const        p_desc,\r
302                 OUT                     NET_BUFFER_LIST** const         pp_net_buffer_list );\r
303 \r
304 static uint32_t\r
305 __recv_mgr_build_NBL_array(\r
306         IN                              ipoib_port_t* const                     p_port,\r
307                 OUT                     cl_qlist_t*                                     p_done_list,\r
308                 OUT                     int32_t* const                          p_discarded );\r
309 \r
310 /******************************************************************************\r
311 *\r
312 * Send manager operations.\r
313 *\r
314 ******************************************************************************/\r
315 static void\r
316 __send_mgr_construct(\r
317         IN                              ipoib_port_t* const                     p_port );\r
318 \r
319 static ib_api_status_t\r
320 __send_mgr_init(\r
321         IN                              ipoib_port_t* const                     p_port );\r
322 \r
323 \r
324 static void\r
325 __send_mgr_destroy(\r
326         IN                              ipoib_port_t* const                     p_port );\r
327 \r
328 static NDIS_STATUS\r
329 __send_gen(\r
330         IN                              ipoib_port_t* const                     p_port,\r
331         IN                              ipoib_send_NB_SG *                      s_buf,\r
332         IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
333         IN                              INT                                             lso_data_index,\r
334         IN                              NET_BUFFER                                      *p_netbuf,\r
335         IN                              UINT                                            lso_header_size OPTIONAL);\r
336 \r
337 static NDIS_STATUS\r
338 __send_mgr_filter_ip(\r
339         IN                              ipoib_port_t* const                     p_port,\r
340         IN              const   eth_hdr_t* const                        p_eth_hdr,\r
341         IN                              MDL*                                            p_mdl,\r
342         IN                              size_t                                          buf_len,\r
343         IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
344         IN      OUT                     ipoib_send_NB_SG* const         s_buf,\r
345         IN                              NET_BUFFER                                      *p_netbuf);\r
346 \r
347 static NDIS_STATUS\r
348 __send_mgr_filter_igmp_v2(\r
349         IN                              ipoib_port_t* const                     p_port,\r
350     IN          const   ip_hdr_t* const                         p_ip_hdr,\r
351         IN                              size_t                                          iph_options_size,\r
352         IN                              MDL*                                            p_mdl,\r
353         IN                              size_t                                          buf_len );\r
354 \r
355 static NDIS_STATUS\r
356 __send_mgr_filter_udp(\r
357         IN                              ipoib_port_t* const                     p_port,\r
358         IN              const   ip_hdr_t* const                         p_ip_hdr,\r
359         IN                              MDL*                                            p_mdl,\r
360         IN                              size_t                                          buf_len,\r
361         IN      OUT                     ipoib_send_NB_SG* const         s_buf);\r
362 \r
363 static NDIS_STATUS\r
364 __send_mgr_filter_dhcp(\r
365         IN                              ipoib_port_t* const                     p_port,\r
366         IN              const   udp_hdr_t* const                        p_udp_hdr,\r
367         IN                              MDL*                                            p_mdl,\r
368         IN                              size_t                                          buf_len,\r
369         IN      OUT                     ipoib_send_NB_SG* const         s_buf );\r
370 \r
371 static NDIS_STATUS\r
372 __send_mgr_filter_arp(\r
373         IN                              ipoib_port_t* const                     p_port,\r
374         IN              const   eth_hdr_t* const                        p_eth_hdr,\r
375         IN                              MDL*                                            p_mdl,\r
376         IN                              size_t                                          buf_len,\r
377         IN      OUT                     ipoib_send_NB_SG* const         s_buf );\r
378 \r
379 static inline void \r
380 __send_complete_net_buffer(\r
381         IN      ipoib_send_NB_SG        *s_buf, \r
382         IN      NDIS_STATUS             status,\r
383         IN      ULONG                           compl_flags,\r
384         IN      boolean_t                       bLock   );\r
385 \r
386 \r
387 static inline NDIS_STATUS\r
388 __send_mgr_queue(\r
389         IN                              ipoib_port_t* const                     p_port,\r
390         IN                              eth_hdr_t* const                        p_eth_hdr,\r
391                 OUT                     ipoib_endpt_t** const           pp_endpt );\r
392 \r
393 static NDIS_STATUS\r
394 __build_send_desc(\r
395         IN                              ipoib_port_t* const                     p_port,\r
396         IN                              eth_hdr_t* const                        p_eth_hdr,\r
397         IN                              MDL* const                                      p_mdl,\r
398         IN              const   size_t                                          mdl_len,\r
399         IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
400         IN                              NET_BUFFER                                      *p_netbuf,\r
401         IN                              ipoib_send_NB_SG                        *s_buf);\r
402 \r
403 \r
404 static void\r
405 __send_cb(\r
406         IN              const   ib_cq_handle_t                          h_cq,\r
407         IN                              void                                            *cq_context );\r
408 \r
409 static NDIS_STATUS \r
410 GetLsoHeaderSize(\r
411         IN              PNET_BUFFER             pNetBuffer,\r
412         IN              LsoData                 *pLsoData,\r
413         OUT     UINT                    *IndexOfData,\r
414         IN              ipoib_hdr_t *ipoib_hdr );\r
415 \r
416 \r
417 static NDIS_STATUS\r
418 __build_lso_desc(\r
419         IN                              ipoib_port_t* const                     p_port,\r
420         IN                              ULONG                                           mss,\r
421         IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
422         IN                              int32_t                                         hdr_idx,\r
423         IN PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO p_lso_info,\r
424         IN                              NET_BUFFER                                      *p_netbuf);\r
425 \r
426 //TODO CM Restore\r
427 #if 0\r
428 \r
429 static NDIS_STATUS\r
430 __send_fragments(\r
431         IN              ipoib_port_t* const                                     p_port,\r
432         IN              ipoib_send_desc_t* const                        p_desc,\r
433         IN              eth_hdr_t* const                                        p_eth_hdr,\r
434         IN              ip_hdr_t* const                                         p_ip_hdr,\r
435         IN              uint32_t                                                        buf_len,\r
436         IN              NDIS_BUFFER*                                            p_ndis_buf );\r
437 \r
438 \r
439 static void\r
440 __update_fragment_ip_hdr(\r
441 IN              ip_hdr_t* const         p_ip_hdr,\r
442 IN              uint16_t                        fragment_size, \r
443 IN              uint16_t                        fragment_offset, \r
444 IN              BOOLEAN                         more_fragments );\r
445 \r
446 static void\r
447 __copy_ip_options(\r
448 IN              uint8_t*                        p_buf,\r
449 IN              uint8_t*                        p_options,\r
450 IN              uint32_t                        options_len,\r
451 IN              BOOLEAN                         copy_all );\r
452 #endif\r
453 /******************************************************************************\r
454 *\r
455 * Endpoint manager operations\r
456 *\r
457 ******************************************************************************/\r
458 static void\r
459 __endpt_mgr_construct(\r
460         IN                              ipoib_port_t* const                     p_port );\r
461 \r
462 static ib_api_status_t\r
463 __endpt_mgr_init(\r
464         IN                              ipoib_port_t* const                     p_port );\r
465 \r
466 static void\r
467 __endpt_mgr_destroy(\r
468         IN                              ipoib_port_t* const                     p_port );\r
469 \r
470 /****f* IPoIB/__endpt_mgr_remove_all\r
471 * NAME\r
472 *       __endpt_mgr_remove_all\r
473 *\r
474 * DESCRIPTION\r
475 *       Removes all enpoints from the port, dereferencing them to initiate\r
476 *       destruction.\r
477 *\r
478 * SYNOPSIS\r
479 */\r
480 static void\r
481 __endpt_mgr_remove_all(\r
482         IN                              ipoib_port_t* const                     p_port );\r
483 /*\r
484 ********/\r
485 \r
486 static void\r
487 __endpt_mgr_remove(\r
488         IN                              ipoib_port_t* const                     p_port,\r
489         IN                              ipoib_endpt_t* const            p_endpt );\r
490 \r
491 static void\r
492 __endpt_mgr_reset_all(\r
493         IN                              ipoib_port_t* const                     p_port );\r
494 \r
495 static inline NDIS_STATUS\r
496 __endpt_mgr_ref(\r
497         IN                              ipoib_port_t* const                     p_port,\r
498         IN              const   mac_addr_t                                      mac,\r
499                 OUT                     ipoib_endpt_t** const           pp_endpt );\r
500 \r
501 static inline NDIS_STATUS\r
502 __endpt_mgr_get_gid_qpn(\r
503         IN                              ipoib_port_t* const                     p_port,\r
504         IN              const   mac_addr_t                                      mac,\r
505                 OUT                     ib_gid_t* const                         p_gid,\r
506                 OUT                     UNALIGNED net32_t* const        p_qpn );\r
507 \r
508 static inline ipoib_endpt_t*\r
509 __endpt_mgr_get_by_gid(\r
510         IN                              ipoib_port_t* const                     p_port,\r
511         IN              const   ib_gid_t* const                         p_gid );\r
512 \r
513 static inline ipoib_endpt_t*\r
514 __endpt_mgr_get_by_lid(\r
515         IN                              ipoib_port_t* const                     p_port,\r
516         IN              const   net16_t                                         lid );\r
517 \r
518 static inline ib_api_status_t\r
519 __endpt_mgr_insert_locked(\r
520         IN                              ipoib_port_t* const                     p_port,\r
521         IN              const   mac_addr_t                                      mac,\r
522         IN                              ipoib_endpt_t* const            p_endpt );\r
523 \r
524 static inline ib_api_status_t\r
525 __endpt_mgr_insert(\r
526         IN                              ipoib_port_t* const                     p_port,\r
527         IN              const   mac_addr_t                                      mac,\r
528         IN                              ipoib_endpt_t* const            p_endpt );\r
529 \r
530 static ib_api_status_t\r
531 __endpt_mgr_add_local(\r
532         IN                              ipoib_port_t* const                     p_port,\r
533         IN                              ib_port_info_t* const           p_port_info );\r
534 \r
535 static ib_api_status_t\r
536 __endpt_mgr_add_bcast(\r
537         IN                              ipoib_port_t* const                     p_port,\r
538         IN                              ib_mcast_rec_t                          *p_mcast_rec );\r
539 \r
540 /******************************************************************************\r
541 *\r
542 * MCast operations.\r
543 *\r
544 ******************************************************************************/\r
545 static ib_api_status_t\r
546 __port_get_bcast(\r
547         IN                              ipoib_port_t* const                     p_port );\r
548 \r
549 static ib_api_status_t\r
550 __port_join_bcast(\r
551         IN                              ipoib_port_t* const                     p_port,\r
552         IN                              ib_member_rec_t* const          p_member_rec );\r
553 \r
554 static ib_api_status_t\r
555 __port_create_bcast(\r
556         IN                              ipoib_port_t* const                     p_port );\r
557 \r
558 \r
559 \r
560 static void\r
561 __bcast_get_cb(\r
562         IN                              ib_query_rec_t                          *p_query_rec );\r
563 \r
564 \r
565 static void\r
566 __bcast_cb(\r
567         IN                              ib_mcast_rec_t                          *p_mcast_rec );\r
568 \r
569 \r
570 static void\r
571 __mcast_cb(\r
572         IN                              ib_mcast_rec_t                          *p_mcast_rec );\r
573 \r
574 void\r
575 __leave_error_mcast_cb(\r
576         IN                              void                            *context );\r
577 \r
578 \r
579 static intn_t\r
580 __gid_cmp(\r
581         IN              const   void* const                                     p_key1,\r
582         IN              const   void* const                                     p_key2 )\r
583 {\r
584         return cl_memcmp( p_key1, p_key2, sizeof(ib_gid_t) );\r
585 }\r
586 \r
587 \r
588 inline void ipoib_port_ref( ipoib_port_t * p_port, int type )\r
589 {\r
590         cl_obj_ref( &p_port->obj );\r
591 #if DBG\r
592         cl_atomic_inc( &p_port->ref[type % ref_mask] );\r
593         if ((p_port->obj.ref_cnt % 20)==0)\r
594         IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
595                 ("ref type %d ref_cnt %d\n", type, p_port->obj.ref_cnt) );\r
596 #else\r
597         UNREFERENCED_PARAMETER(type);\r
598 #endif\r
599 }\r
600 \r
601 \r
602 inline void ipoib_port_deref(ipoib_port_t * p_port, int type)\r
603 {\r
604 #if DBG\r
605         cl_atomic_dec( &p_port->ref[type % ref_mask] );\r
606         if ((p_port->obj.ref_cnt % 20) == 0)\r
607         IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
608                 ("deref type %d ref_cnt %d\n", type, p_port->obj.ref_cnt) );\r
609 #else\r
610         UNREFERENCED_PARAMETER(type);\r
611 #endif\r
612         cl_obj_deref( &p_port->obj );\r
613 \r
614 }\r
615 \r
616 /* function returns pointer to payload that is going after IP header.\r
617 *  asssuming that payload and IP header are in the same buffer\r
618 */\r
619 static void* GetIpPayloadPtr(const      ip_hdr_t* const p_ip_hdr)\r
620 {\r
621         return (void*)((uint8_t*)p_ip_hdr + IP_HEADER_LENGTH(p_ip_hdr));\r
622 }\r
623 \r
624 /******************************************************************************\r
625 *\r
626 * Implementation\r
627 *\r
628 ******************************************************************************/\r
629 ib_api_status_t\r
630 ipoib_create_port(\r
631         IN                              ipoib_adapter_t* const          p_adapter,\r
632         IN                              ib_pnp_port_rec_t* const        p_pnp_rec,\r
633                 OUT                     ipoib_port_t** const            pp_port )\r
634 {\r
635         ib_api_status_t         status;\r
636         ipoib_port_t            *p_port;\r
637 \r
638         IPOIB_ENTER( IPOIB_DBG_INIT );\r
639 \r
640         CL_ASSERT( !p_adapter->p_port );\r
641 \r
642         p_port = (ipoib_port_t *) cl_zalloc( sizeof(ipoib_port_t) +\r
643                 (sizeof(ipoib_hdr_t) * (p_adapter->params.sq_depth - 1)) );\r
644         if( !p_port )\r
645         {\r
646                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
647                         ("Failed to allocate ipoib_port_t (%d bytes)\n",\r
648                         sizeof(ipoib_port_t)) );\r
649                 return IB_INSUFFICIENT_MEMORY;\r
650         }\r
651 \r
652 #ifdef _DEBUG_\r
653         gp_ipoib_port = p_port;\r
654 #endif\r
655 \r
656         __port_construct( p_port );\r
657 \r
658         status = __port_init( p_port, p_adapter, p_pnp_rec );\r
659         if( status != IB_SUCCESS )\r
660         {\r
661                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
662                         ("ipoib_port_init returned %s.\n", \r
663                         p_adapter->p_ifc->get_err_str( status )) );\r
664                 __port_cleanup( &p_port->obj );\r
665                 __port_free( &p_port->obj );\r
666                 return status;\r
667         }\r
668 \r
669         *pp_port = p_port;\r
670         IPOIB_EXIT( IPOIB_DBG_INIT );\r
671         return IB_SUCCESS;\r
672 }\r
673 \r
674 \r
675 void\r
676 ipoib_port_destroy(\r
677         IN                              ipoib_port_t* const                     p_port )\r
678 {\r
679         IPOIB_ENTER( IPOIB_DBG_INIT );\r
680 \r
681         CL_ASSERT( p_port );\r
682         CL_ASSERT( p_port->p_adapter );\r
683         CL_ASSERT( !p_port->p_adapter->p_port );\r
684 \r
685         cl_obj_destroy( &p_port->obj );\r
686 \r
687         IPOIB_EXIT( IPOIB_DBG_INIT );\r
688 }\r
689 \r
690 \r
691 static void\r
692 __port_construct(\r
693         IN                              ipoib_port_t* const                     p_port )\r
694 {\r
695         IPOIB_ENTER( IPOIB_DBG_INIT );\r
696 \r
697         p_port->state = IB_QPS_RESET;\r
698 \r
699         cl_obj_construct( &p_port->obj, IPOIB_OBJ_PORT );\r
700         cl_spinlock_construct( &p_port->send_lock );\r
701         cl_spinlock_construct( &p_port->recv_lock );\r
702         __ib_mgr_construct( p_port );\r
703         __buf_mgr_construct( p_port );\r
704 \r
705         __recv_mgr_construct( p_port );\r
706         __send_mgr_construct( p_port );\r
707 \r
708         __endpt_mgr_construct( p_port );\r
709 \r
710         KeInitializeEvent( &p_port->sa_event, NotificationEvent, TRUE );\r
711         KeInitializeEvent( &p_port->leave_mcast_event, NotificationEvent, TRUE );\r
712         \r
713         IPOIB_EXIT( IPOIB_DBG_INIT );\r
714 }\r
715 \r
716 \r
717 static ib_api_status_t\r
718 __port_init(\r
719         IN                              ipoib_port_t* const                     p_port,\r
720         IN                              ipoib_adapter_t* const          p_adapter,\r
721         IN                              ib_pnp_port_rec_t* const        p_pnp_rec )\r
722 {\r
723         cl_status_t                     cl_status;\r
724         ib_api_status_t         status;\r
725 \r
726         IPOIB_ENTER( IPOIB_DBG_INIT );\r
727 \r
728         p_port->port_num = p_pnp_rec->p_port_attr->port_num;\r
729         p_port->p_adapter = p_adapter;\r
730 \r
731         cl_status = cl_spinlock_init( &p_port->send_lock );\r
732         if( cl_status != CL_SUCCESS )\r
733         {\r
734                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
735                         ("cl_spinlock_init returned %#x\n", cl_status) );\r
736                 return IB_ERROR;\r
737         }\r
738 \r
739         cl_status = cl_spinlock_init( &p_port->recv_lock );\r
740         if( cl_status != CL_SUCCESS )\r
741         {\r
742                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
743                         ("cl_spinlock_init returned %#x\n", cl_status) );\r
744                 return IB_ERROR;\r
745         }\r
746 \r
747         /* Initialize the IB resource manager. */\r
748         status = __ib_mgr_init( p_port );\r
749         if( status != IB_SUCCESS )\r
750         {\r
751                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
752                         ("__ib_mgr_init returned %s\n", \r
753                         p_adapter->p_ifc->get_err_str( status )) );\r
754                 return status;\r
755         }\r
756 \r
757         /* Initialize the buffer manager. */\r
758         status = __buf_mgr_init( p_port );\r
759         if( status != IB_SUCCESS )\r
760         {\r
761                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
762                         ("__buf_mgr_init returned %s\n", \r
763                         p_adapter->p_ifc->get_err_str( status )) );\r
764                 return status;\r
765         }\r
766 \r
767         /* Initialize the receive manager. */\r
768         status = __recv_mgr_init( p_port );\r
769         if( status != IB_SUCCESS )\r
770         {\r
771                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
772                         ("__recv_mgr_init returned %s\n", \r
773                         p_adapter->p_ifc->get_err_str( status )) );\r
774                 return status;\r
775         }\r
776         \r
777         status =__send_mgr_init( p_port );\r
778         if( status != IB_SUCCESS )\r
779         {\r
780                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
781                         ("__send_mgr_init returned %s\n", \r
782                         p_adapter->p_ifc->get_err_str( status )) );\r
783                 return status;\r
784         }\r
785 \r
786         /* Initialize the endpoint manager. */\r
787         status = __endpt_mgr_init( p_port );\r
788         if( status != IB_SUCCESS )\r
789         {\r
790                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
791                         ("__endpt_mgr_init returned %s\n", \r
792                         p_adapter->p_ifc->get_err_str( status )) );\r
793                 return status;\r
794         }\r
795 \r
796          KeInitializeDpc(&p_port->recv_dpc,(PKDEFERRED_ROUTINE)__recv_cb_dpc,p_port);\r
797 \r
798 \r
799          /* Initialize multicast garbage collector timer and DPC object */\r
800          KeInitializeDpc(&p_port->gc_dpc,(PKDEFERRED_ROUTINE)__port_mcast_garbage_dpc,p_port);\r
801          KeInitializeTimerEx(&p_port->gc_timer,SynchronizationTimer);\r
802 \r
803         /* We only ever destroy from the PnP callback thread. */\r
804         cl_status = cl_obj_init( &p_port->obj, CL_DESTROY_SYNC,\r
805                 __port_destroying, __port_cleanup, __port_free );\r
806 \r
807 #if DBG\r
808         cl_atomic_inc( &p_port->ref[ref_init] );\r
809         IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
810                 ("ref type %d ref_cnt %d\n", ref_init, p_port->obj.ref_cnt) );\r
811 #endif\r
812 \r
813         if( cl_status != CL_SUCCESS )\r
814         {\r
815                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
816                         ("cl_obj_init returned %#x\n", cl_status) );\r
817                 return IB_ERROR;\r
818         }\r
819 \r
820         cl_status = cl_obj_insert_rel( &p_port->rel, &p_adapter->obj, &p_port->obj );\r
821         if( cl_status != CL_SUCCESS )\r
822         {\r
823                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
824                         ("cl_obj_insert_rel returned %#x\n", cl_status) );\r
825                 cl_obj_destroy( &p_port->obj );\r
826                 return IB_ERROR;\r
827         }\r
828 \r
829 #if DBG\r
830         cl_atomic_inc( &p_port->ref[ref_init] );\r
831         IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_OBJ,\r
832                 ("ref type %d ref_cnt %d\n", ref_init, p_port->obj.ref_cnt) );\r
833 #endif\r
834 \r
835         IPOIB_EXIT( IPOIB_DBG_INIT );\r
836         return IB_SUCCESS;\r
837 }\r
838 \r
839 \r
840 static void\r
841 __port_destroying(\r
842         IN                              cl_obj_t* const                         p_obj )\r
843 {\r
844         ipoib_port_t    *p_port;\r
845 \r
846         IPOIB_ENTER( IPOIB_DBG_INIT );\r
847 \r
848         CL_ASSERT( p_obj );\r
849 \r
850         p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj );\r
851 \r
852         ipoib_port_down( p_port );\r
853 \r
854         __endpt_mgr_remove_all( p_port );\r
855 \r
856 #if 0\r
857         if( p_port->p_adapter->params.cm_enabled )\r
858         {\r
859                 endpt_cm_buf_mgr_destroy(  p_port );\r
860                 ipoib_port_srq_destroy( p_port );\r
861                 p_port->endpt_mgr.thread_is_done = 1;\r
862                 cl_event_signal( &p_port->endpt_mgr.event );\r
863         }\r
864 #endif\r
865         cl_spinlock_acquire(&p_port->send_lock);\r
866         ipoib_port_resume( p_port, FALSE );\r
867         cl_spinlock_release(&p_port->send_lock);\r
868 \r
869         IPOIB_EXIT( IPOIB_DBG_INIT );\r
870 }\r
871 \r
872 \r
873 static void\r
874 __port_cleanup(\r
875         IN                              cl_obj_t* const                         p_obj )\r
876 {\r
877         ipoib_port_t    *p_port;\r
878 \r
879         IPOIB_ENTER( IPOIB_DBG_INIT );\r
880 \r
881         CL_ASSERT( p_obj );\r
882 \r
883         p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj );\r
884 \r
885         /* Wait for all sends and receives to get flushed. */\r
886         while( p_port->send_mgr.depth || p_port->recv_mgr.depth )\r
887                 cl_thread_suspend( 0 );\r
888 \r
889         /* Destroy the send and receive managers before closing the CA. */\r
890         __ib_mgr_destroy( p_port );\r
891 \r
892         IPOIB_EXIT( IPOIB_DBG_INIT );\r
893 }\r
894 \r
895 \r
896 static void\r
897 __port_free(\r
898         IN                              cl_obj_t* const                         p_obj )\r
899 {\r
900         ipoib_port_t    *p_port;\r
901 \r
902         IPOIB_ENTER( IPOIB_DBG_INIT );\r
903 \r
904         CL_ASSERT( p_obj );\r
905 \r
906         p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj );\r
907 \r
908         KeCancelTimer(&p_port->gc_timer);\r
909         KeFlushQueuedDpcs();\r
910         __endpt_mgr_destroy( p_port );\r
911         __recv_mgr_destroy( p_port );\r
912         __send_mgr_destroy( p_port );\r
913         __buf_mgr_destroy( p_port );\r
914 \r
915         cl_spinlock_destroy( &p_port->send_lock );\r
916         cl_spinlock_destroy( &p_port->recv_lock );\r
917 \r
918         cl_obj_deinit( p_obj );\r
919         if( p_port->p_ca_attrs )\r
920         {\r
921                 cl_free ( p_port->p_ca_attrs );\r
922         }\r
923         cl_free( p_port );\r
924 \r
925         IPOIB_EXIT( IPOIB_DBG_INIT );\r
926 }\r
927 \r
928 \r
929 \r
930 /******************************************************************************\r
931 *\r
932 * IB resource manager implementation.\r
933 *\r
934 ******************************************************************************/\r
935 static void\r
936 __ib_mgr_construct(\r
937         IN                              ipoib_port_t* const                     p_port )\r
938 {\r
939         IPOIB_ENTER( IPOIB_DBG_INIT );\r
940 \r
941         cl_memclr( &p_port->ib_mgr, sizeof(ipoib_ib_mgr_t) );\r
942 \r
943         IPOIB_EXIT( IPOIB_DBG_INIT );\r
944 }\r
945 \r
946 \r
947 static ib_api_status_t\r
948 __ib_mgr_init(\r
949         IN                              ipoib_port_t* const                     p_port )\r
950 {\r
951         ib_api_status_t         status;\r
952         ib_cq_create_t          cq_create;\r
953         ib_qp_create_t          qp_create;\r
954         ib_phys_create_t        phys_create;\r
955         ib_phys_range_t         phys_range;\r
956         uint64_t                        vaddr;\r
957         net32_t                         rkey;\r
958         ib_qp_attr_t            qp_attr;\r
959 \r
960         IPOIB_ENTER( IPOIB_DBG_INIT );\r
961 \r
962         /* Open the CA. */\r
963         status = p_port->p_adapter->p_ifc->open_ca(\r
964                 p_port->p_adapter->h_al, p_port->p_adapter->guids.ca_guid,\r
965                 NULL, p_port, &p_port->ib_mgr.h_ca );\r
966         if( status != IB_SUCCESS )\r
967         {\r
968                 NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
969                         EVENT_IPOIB_OPEN_CA, 1, status );\r
970                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
971                         ("ib_open_ca returned %s\n", \r
972                         p_port->p_adapter->p_ifc->get_err_str( status )) );\r
973                 return status;\r
974         }\r
975 \r
976         status = __port_query_ca_attrs( p_port, &p_port->p_ca_attrs );\r
977         if( status != IB_SUCCESS )\r
978         {\r
979                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
980                         ("Query CA attributes failed\n" ) );\r
981                 return status;\r
982         }\r
983 #if 0\r
984         if( p_port->p_adapter->params.cm_enabled )\r
985         {\r
986                 uint32_t payload_mtu = __port_attr_to_mtu_size( \r
987                         p_port->p_ca_attrs->p_port_attr[p_port->port_num - 1].mtu )\r
988                         - sizeof(ipoib_hdr_t);\r
989                 /* adjust ipoib UD payload MTU to actual port MTU size. */\r
990                 p_port->p_adapter->params.payload_mtu = \r
991                                 max( DEFAULT_PAYLOAD_MTU, payload_mtu );\r
992                 p_port->p_adapter->params.xfer_block_size = \r
993                         (sizeof(eth_hdr_t) + p_port->p_adapter->params.payload_mtu);\r
994         }\r
995 #endif\r
996 #if IPOIB_USE_DMA\r
997         /* init DMA only once while running MiniportInitialize */\r
998         if ( !p_port->p_adapter->reset )\r
999         {\r
1000                 ULONG max_phys_mapping;\r
1001                 if( p_port->p_adapter->params.cm_enabled )\r
1002                 {\r
1003                         max_phys_mapping = p_port->p_adapter->params.cm_xfer_block_size;\r
1004                 }\r
1005                 else if( p_port->p_adapter->params.lso )\r
1006                 {\r
1007                         max_phys_mapping = LARGE_SEND_OFFLOAD_SIZE;\r
1008                 }\r
1009                 else\r
1010                 {\r
1011                         max_phys_mapping = p_port->p_adapter->params.xfer_block_size;\r
1012                 }\r
1013                 /*if( NdisMInitializeScatterGatherDma( p_port->p_adapter->h_adapter,\r
1014                                                         TRUE, max_phys_mapping )!= NDIS_STATUS_SUCCESS )\r
1015                 {\r
1016                         IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1017                                 ("NdisMInitializeScatterGatherDma failed\n" ) );\r
1018                         return IB_INSUFFICIENT_RESOURCES;\r
1019                 }*/\r
1020         }\r
1021 #endif\r
1022 \r
1023         /* Allocate the PD. */\r
1024         status = p_port->p_adapter->p_ifc->alloc_pd(\r
1025                 p_port->ib_mgr.h_ca, IB_PDT_UD, p_port, &p_port->ib_mgr.h_pd );\r
1026         if( status != IB_SUCCESS )\r
1027         {\r
1028                 NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
1029                         EVENT_IPOIB_ALLOC_PD, 1, status );\r
1030                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1031                         ("ib_alloc_pd returned %s\n", \r
1032                         p_port->p_adapter->p_ifc->get_err_str( status )) );\r
1033                 return status;\r
1034         }\r
1035 \r
1036         /* Allocate receive CQ. */\r
1037         cq_create.size = p_port->p_adapter->params.rq_depth;\r
1038         cq_create.pfn_comp_cb = __recv_cb;\r
1039         cq_create.h_wait_obj = NULL;\r
1040 \r
1041         status = p_port->p_adapter->p_ifc->create_cq(\r
1042                 p_port->ib_mgr.h_ca, &cq_create, p_port,\r
1043                 __cq_event, &p_port->ib_mgr.h_recv_cq );\r
1044         if( status != IB_SUCCESS )\r
1045         {\r
1046                 NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
1047                         EVENT_IPOIB_CREATE_RECV_CQ, 1, status );\r
1048                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1049                         ("ib_create_cq returned %s.\n", \r
1050                         p_port->p_adapter->p_ifc->get_err_str( status )) );\r
1051                 return status;\r
1052         }\r
1053 \r
1054         /* Allocate send CQ. */\r
1055         cq_create.size = p_port->p_adapter->params.sq_depth;\r
1056         cq_create.pfn_comp_cb = __send_cb;\r
1057 \r
1058         status = p_port->p_adapter->p_ifc->create_cq(\r
1059                 p_port->ib_mgr.h_ca, &cq_create, p_port,\r
1060                 __cq_event, &p_port->ib_mgr.h_send_cq );\r
1061         if( status != IB_SUCCESS )\r
1062         {\r
1063                 NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
1064                         EVENT_IPOIB_CREATE_SEND_CQ, 1, status );\r
1065                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1066                         ("ib_create_cq returned %s.\n", \r
1067                         p_port->p_adapter->p_ifc->get_err_str( status )) );\r
1068                 return status;\r
1069         }\r
1070         \r
1071         /* Allocate the QP. */\r
1072         cl_memclr( &qp_create, sizeof(qp_create) );\r
1073         qp_create.qp_type = IB_QPT_UNRELIABLE_DGRM;\r
1074         qp_create.rq_depth = p_port->p_adapter->params.rq_depth;\r
1075         qp_create.rq_sge = 2;   /* To support buffers spanning pages. */\r
1076         qp_create.h_rq_cq = p_port->ib_mgr.h_recv_cq;\r
1077         qp_create.sq_depth = p_port->p_adapter->params.sq_depth;\r
1078 \r
1079 #define UD_QP_USED_SGE 3\r
1080         qp_create.sq_sge = MAX_SEND_SGE < p_port->p_ca_attrs->max_sges ? \r
1081                         MAX_SEND_SGE  : ( p_port->p_ca_attrs->max_sges - UD_QP_USED_SGE );\r
1082         if ( !p_port->p_ca_attrs->ipoib_csum ) \r
1083         { \r
1084                 /* checksum is not supported by device\r
1085                 user must specify BYPASS to explicitly cancel checksum calculation */\r
1086                 if (p_port->p_adapter->params.send_chksum_offload == CSUM_ENABLED)\r
1087                         p_port->p_adapter->params.send_chksum_offload = CSUM_DISABLED;\r
1088                 if (p_port->p_adapter->params.recv_chksum_offload == CSUM_ENABLED)\r
1089                         p_port->p_adapter->params.recv_chksum_offload = CSUM_DISABLED;\r
1090         }\r
1091 \r
1092 \r
1093         // Now, params struct contains the intersection between the user definition\r
1094         // and actual HW capabilites\r
1095         // Remember these values for NDIS OID requests\r
1096         p_port->p_adapter->offload_cap.lso = !!(p_port->p_adapter->params.lso);\r
1097         p_port->p_adapter->offload_cap.send_chksum_offload = \r
1098                 !! (p_port->p_adapter->params.send_chksum_offload);\r
1099         p_port->p_adapter->offload_cap.recv_chksum_offload = \r
1100                 !! (p_port->p_adapter->params.recv_chksum_offload);\r
1101         \r
1102         \r
1103         \r
1104         \r
1105         qp_create.h_sq_cq = p_port->ib_mgr.h_send_cq;\r
1106         qp_create.sq_signaled = FALSE;\r
1107         status = p_port->p_adapter->p_ifc->create_qp(\r
1108                 p_port->ib_mgr.h_pd, &qp_create, p_port,\r
1109                 __qp_event, &p_port->ib_mgr.h_qp );\r
1110         if( status != IB_SUCCESS )\r
1111         {\r
1112                 NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
1113                         EVENT_IPOIB_CREATE_QP, 1, status );\r
1114                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1115                         ("ib_create_qp returned %s\n", \r
1116                         p_port->p_adapter->p_ifc->get_err_str( status )) );\r
1117                 return status;\r
1118         }\r
1119         /* Query the QP so we can get our QPN. */\r
1120         status = p_port->p_adapter->p_ifc->query_qp(\r
1121                 p_port->ib_mgr.h_qp, &qp_attr );\r
1122         if( status != IB_SUCCESS )\r
1123         {\r
1124                 NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
1125                         EVENT_IPOIB_QUERY_QP, 1, status );\r
1126                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1127                         ("ib_query_qp returned %s\n", \r
1128                         p_port->p_adapter->p_ifc->get_err_str( status )) );\r
1129                 return status;\r
1130         }\r
1131         p_port->ib_mgr.qpn = qp_attr.num;\r
1132 \r
1133         /* Register all of physical memory */\r
1134         phys_create.length = MEM_REG_SIZE;\r
1135         phys_create.num_ranges = 1;\r
1136         phys_create.range_array = &phys_range;\r
1137         phys_create.buf_offset = 0;\r
1138         phys_create.hca_page_size = PAGE_SIZE;\r
1139         phys_create.access_ctrl = IB_AC_LOCAL_WRITE;\r
1140         phys_range.base_addr = 0;\r
1141         phys_range.size = MEM_REG_SIZE;\r
1142         vaddr = 0;\r
1143         status = p_port->p_adapter->p_ifc->reg_phys(\r
1144                 p_port->ib_mgr.h_pd, &phys_create, &vaddr,\r
1145                 &p_port->ib_mgr.lkey, &rkey, &p_port->ib_mgr.h_mr );\r
1146         if( status != IB_SUCCESS )\r
1147         {\r
1148                 NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
1149                         EVENT_IPOIB_REG_PHYS, 1, status );\r
1150                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1151                         ("ib_reg_phys returned %s\n", \r
1152                         p_port->p_adapter->p_ifc->get_err_str( status )) );\r
1153                 return status;\r
1154         }\r
1155 \r
1156         status = ipoib_port_srq_init( p_port );\r
1157         if( status != IB_SUCCESS )\r
1158         {\r
1159                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1160                         ("ipoib_port_srq_init failed %s\n",\r
1161                         p_port->p_adapter->p_ifc->get_err_str( status )) );\r
1162                 /* disable further CM initialization */\r
1163                 p_port->p_adapter->params.cm_enabled = FALSE;\r
1164 \r
1165                 NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
1166                                 EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de1 );\r
1167 \r
1168         }\r
1169 //CM\r
1170 #if 0\r
1171         if( p_port->p_adapter->params.cm_enabled )\r
1172         {\r
1173                 status = endpt_cm_buf_mgr_init( p_port );\r
1174                 if( status != IB_SUCCESS )\r
1175                 {\r
1176                         IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1177                                 ("CM Init buf mgr failed status %#x\n", status ) );\r
1178                         ipoib_port_srq_destroy( p_port );\r
1179                         p_port->p_adapter->params.cm_enabled = FALSE;\r
1180 \r
1181                         NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
1182                                 EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de2 );\r
1183                 }\r
1184                 else \r
1185                 {\r
1186                         if ( p_port->p_adapter->params.send_chksum_offload )\r
1187                         p_port->p_adapter->params.send_chksum_offload = CSUM_DISABLED;\r
1188                 }\r
1189         }\r
1190 #endif\r
1191         IPOIB_EXIT( IPOIB_DBG_INIT );\r
1192         return IB_SUCCESS;\r
1193 }\r
1194 \r
1195 static void\r
1196 __srq_async_event_cb(\r
1197 IN                      ib_async_event_rec_t            *p_event_rec )\r
1198 {\r
1199         ipoib_port_t* p_port = \r
1200                 (ipoib_port_t *)p_event_rec->context;\r
1201 \r
1202         switch( p_event_rec->code )\r
1203         {\r
1204         case IB_AE_SRQ_LIMIT_REACHED:\r
1205                                 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1206                         ("SRQ ASYNC EVENT CODE %d: %s\n", \r
1207                         p_event_rec->code, "IB_AE_SRQ_LIMIT_REACHED" ) );\r
1208                         break;\r
1209         case IB_AE_SRQ_CATAS_ERROR:\r
1210                         IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1211                                 ("SRQ ASYNC EVENT CODE %d: %s\n", \r
1212                                 p_event_rec->code, "IB_AE_SRQ_CATAS_ERROR" ) );\r
1213                         /*SRQ is in err state, must reinitialize */\r
1214                         p_port->p_adapter->hung = TRUE;\r
1215                         break;\r
1216         case IB_AE_SRQ_QP_LAST_WQE_REACHED:\r
1217                         IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1218                                 ("SRQ ASYNC EVENT CODE %d: %s\n", \r
1219                                 p_event_rec->code, "IB_AE_SRQ_QP_LAST_WQE_REACHED" ) );\r
1220                         /*SRQ is in err state, must reinitialize */\r
1221                         p_port->p_adapter->hung = TRUE;\r
1222                         break;\r
1223         default:\r
1224                         IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1225                                 ("ASYNC EVENT CODE ARRIVED %d(%#x)\n", \r
1226                                 p_event_rec->code, p_event_rec->code ) );\r
1227         }\r
1228 }\r
1229 \r
1230 ib_api_status_t\r
1231 ipoib_port_srq_init(\r
1232         IN                              ipoib_port_t* const                     p_port )\r
1233 {\r
1234         ib_api_status_t         ib_status;\r
1235         ib_srq_handle_t         h_srq;\r
1236         ib_srq_attr_t           srq_attr;\r
1237 \r
1238         IPOIB_ENTER( IPOIB_DBG_INIT );\r
1239         \r
1240         if( !p_port->p_adapter->params.cm_enabled )\r
1241                 return IB_SUCCESS;\r
1242 \r
1243         srq_attr.max_sge = min( 2, p_port->p_ca_attrs->max_srq_sges );\r
1244         srq_attr.srq_limit = 10;\r
1245         srq_attr.max_wr = \r
1246                 min( (uint32_t)p_port->p_adapter->params.rq_depth * 8,\r
1247                                 p_port->p_ca_attrs->max_srq_wrs/2 );\r
1248 \r
1249         ib_status = p_port->p_adapter->p_ifc->create_srq( \r
1250                                                                 p_port->ib_mgr.h_pd, \r
1251                                                                 &srq_attr, \r
1252                                                                 p_port, \r
1253                                                                 __srq_async_event_cb, \r
1254                                                                 &h_srq );\r
1255         if( ib_status != IB_SUCCESS )\r
1256         {\r
1257                 NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
1258                         EVENT_IPOIB_CREATE_QP, 1, ib_status );\r
1259                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1260                         ("ib_create_srq failed status %s\n", \r
1261                         p_port->p_adapter->p_ifc->get_err_str( ib_status )) );\r
1262                 return ib_status;\r
1263         }\r
1264         p_port->ib_mgr.h_srq = h_srq;\r
1265 \r
1266         IPOIB_EXIT( IPOIB_DBG_INIT );\r
1267 \r
1268         return ib_status;\r
1269 }\r
1270 \r
1271 /*  __port_query_ca_attrs() \r
1272  *  returns a pointer to allocated memory.\r
1273  *  must be released by caller.\r
1274  */\r
1275 static ib_api_status_t\r
1276 __port_query_ca_attrs( \r
1277         IN              ipoib_port_t* const             p_port,\r
1278         IN              ib_ca_attr_t**                  pp_ca_attrs )\r
1279 {\r
1280         ib_api_status_t         ib_status;\r
1281         uint32_t                        attr_size;\r
1282         ib_ca_attr_t*           p_ca_attrs;\r
1283 \r
1284         *pp_ca_attrs = NULL;\r
1285 \r
1286         ib_status = \r
1287                 p_port->p_adapter->p_ifc->query_ca( p_port->ib_mgr.h_ca, NULL , &attr_size );\r
1288         if( ib_status != IB_INSUFFICIENT_MEMORY )\r
1289         {\r
1290                 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1291                         ("ib_query_ca failed status %s\n",\r
1292                         p_port->p_adapter->p_ifc->get_err_str( ib_status )) );\r
1293                 goto done;\r
1294         }\r
1295         CL_ASSERT( attr_size );\r
1296 \r
1297         p_ca_attrs = (ib_ca_attr_t *) cl_zalloc( attr_size );\r
1298         if ( p_ca_attrs == NULL )\r
1299         {\r
1300                 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1301                         ("Allocate %d bytes failed for CA Attributes\n", attr_size ));\r
1302                 ib_status = IB_INSUFFICIENT_MEMORY;\r
1303                 goto done;\r
1304         }\r
1305 \r
1306         ib_status = \r
1307                 p_port->p_adapter->p_ifc->query_ca( p_port->ib_mgr.h_ca, p_ca_attrs , &attr_size );\r
1308         if ( ib_status != IB_SUCCESS )\r
1309         {\r
1310                 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1311                         ("CA attributes query failed\n") );\r
1312                 cl_free ( p_ca_attrs );\r
1313                 goto done;\r
1314         }\r
1315 \r
1316         *pp_ca_attrs = p_ca_attrs;\r
1317 done:\r
1318         return ib_status;\r
1319 }\r
1320 \r
1321 void\r
1322 ipoib_port_srq_destroy( \r
1323         IN                              ipoib_port_t* const                     p_port )\r
1324 {\r
1325         ib_api_status_t status;\r
1326 \r
1327         if( p_port->ib_mgr.h_srq )\r
1328         {\r
1329                 status =\r
1330                         p_port->p_adapter->p_ifc->destroy_srq( p_port->ib_mgr.h_srq, NULL );\r
1331                 CL_ASSERT( status == IB_SUCCESS );\r
1332                 p_port->ib_mgr.h_srq = NULL;\r
1333         }\r
1334 }\r
1335 \r
1336 static void\r
1337 __ib_mgr_destroy(\r
1338         IN                              ipoib_port_t* const                     p_port )\r
1339 {\r
1340         ib_api_status_t status;\r
1341 \r
1342         IPOIB_ENTER( IPOIB_DBG_INIT );\r
1343 \r
1344         if( p_port->ib_mgr.h_ca )\r
1345         {\r
1346                 status =\r
1347                         p_port->p_adapter->p_ifc->close_ca( p_port->ib_mgr.h_ca, NULL );\r
1348                 CL_ASSERT( status == IB_SUCCESS );\r
1349                 p_port->ib_mgr.h_ca = NULL;\r
1350         }\r
1351 \r
1352         IPOIB_EXIT( IPOIB_DBG_INIT );\r
1353 }\r
1354 \r
1355 \r
1356 \r
1357 /******************************************************************************\r
1358 *\r
1359 * Buffer manager implementation.\r
1360 *\r
1361 ******************************************************************************/\r
1362 static void\r
1363 __buf_mgr_construct(\r
1364         IN                              ipoib_port_t* const                     p_port )\r
1365 {\r
1366         IPOIB_ENTER( IPOIB_DBG_INIT );\r
1367 \r
1368         cl_qpool_construct( &p_port->buf_mgr.recv_pool );\r
1369 \r
1370         p_port->buf_mgr.h_packet_pool = NULL;\r
1371         p_port->buf_mgr.h_buffer_pool = NULL;\r
1372 \r
1373         NdisInitializeNPagedLookasideList( &p_port->buf_mgr.send_buf_list,\r
1374                 NULL, NULL, 0, MAX_XFER_BLOCK_SIZE, 'bipi', 0 );\r
1375 \r
1376         p_port->buf_mgr.h_send_pkt_pool = NULL;\r
1377 \r
1378         IPOIB_EXIT( IPOIB_DBG_INIT );\r
1379 }\r
1380 \r
1381 \r
1382 static ib_api_status_t\r
1383 __buf_mgr_init(\r
1384         IN                              ipoib_port_t* const                     p_port )\r
1385 {\r
1386         cl_status_t             cl_status;\r
1387         ipoib_params_t  *p_params;\r
1388         NET_BUFFER_LIST_POOL_PARAMETERS pool_parameters;\r
1389         IPOIB_ENTER(IPOIB_DBG_INIT );\r
1390 \r
1391         CL_ASSERT( p_port );\r
1392         CL_ASSERT( p_port->p_adapter );\r
1393 \r
1394         p_params = &p_port->p_adapter->params;\r
1395 \r
1396         /* Allocate the receive descriptor pool */\r
1397         cl_status = cl_qpool_init( &p_port->buf_mgr.recv_pool,\r
1398                 p_params->rq_depth * p_params->recv_pool_ratio,\r
1399 #if IPOIB_INLINE_RECV\r
1400                 0, 0, sizeof(ipoib_recv_desc_t), __recv_ctor, NULL, p_port );\r
1401 #else   /* IPOIB_INLINE_RECV */\r
1402                 0, 0, sizeof(ipoib_recv_desc_t), __recv_ctor, __recv_dtor, p_port );\r
1403 #endif  /* IPOIB_INLINE_RECV */\r
1404         if( cl_status != CL_SUCCESS )\r
1405         {\r
1406                 NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
1407                         EVENT_IPOIB_RECV_POOL, 1, cl_status );\r
1408                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1409                         ("cl_qpool_init for recvs returned %#x\n",\r
1410                         cl_status) );\r
1411                 return IB_INSUFFICIENT_MEMORY;\r
1412         }\r
1413 \r
1414         /* Allocate the NET BUFFER list pools for receive indication. */\r
1415         NdisZeroMemory(&pool_parameters, sizeof(NET_BUFFER_LIST_POOL_PARAMETERS));\r
1416     pool_parameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
1417     pool_parameters.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;\r
1418     pool_parameters.Header.Size = sizeof(pool_parameters);\r
1419     pool_parameters.ProtocolId = 0;\r
1420     pool_parameters.ContextSize = 0;\r
1421     pool_parameters.fAllocateNetBuffer = TRUE;\r
1422     pool_parameters.PoolTag = 'CRPI';\r
1423         pool_parameters.DataSize = 0;\r
1424 \r
1425     p_port->buf_mgr.h_packet_pool = NdisAllocateNetBufferListPool(\r
1426                 p_port->p_adapter->h_adapter,\r
1427                 &pool_parameters); \r
1428 \r
1429         if( !p_port->buf_mgr.h_packet_pool )\r
1430         {\r
1431                 NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
1432                         EVENT_IPOIB_RECV_PKT_POOL, 1, NDIS_STATUS_RESOURCES  );\r
1433                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1434                         ("NdisAllocatePacketPool returned %08X\n", (UINT)NDIS_STATUS_RESOURCES) );\r
1435                 return IB_INSUFFICIENT_RESOURCES;\r
1436         }\r
1437         \r
1438         /* Allocate the NET buffer list pool for send formatting. */\r
1439     pool_parameters.PoolTag = 'XTPI';\r
1440 \r
1441     p_port->buf_mgr.h_send_pkt_pool = NdisAllocateNetBufferListPool(\r
1442                 p_port->p_adapter->h_adapter,\r
1443                 &pool_parameters); \r
1444         if( !p_port->buf_mgr.h_send_pkt_pool)\r
1445         {\r
1446                 NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
1447                         EVENT_IPOIB_SEND_PKT_POOL, 1, NDIS_STATUS_RESOURCES );\r
1448                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1449                         ("NdisAllocatePacketPool returned %08X\n", (UINT)NDIS_STATUS_RESOURCES) );\r
1450                 return IB_INSUFFICIENT_RESOURCES;\r
1451         }\r
1452 \r
1453         IPOIB_EXIT( IPOIB_DBG_INIT );\r
1454         return IB_SUCCESS;\r
1455 }\r
1456 \r
1457 \r
1458 static void\r
1459 __buf_mgr_destroy(\r
1460         IN                              ipoib_port_t* const                     p_port )\r
1461 {\r
1462         IPOIB_ENTER(IPOIB_DBG_INIT );\r
1463 \r
1464         CL_ASSERT( p_port );\r
1465 \r
1466         /* Destroy the send packet and buffer pools. \r
1467         if( p_port->buf_mgr.h_send_buf_pool )\r
1468                 NdisFreeBufferPool( p_port->buf_mgr.h_send_buf_pool );*/\r
1469         if( p_port->buf_mgr.h_send_pkt_pool )\r
1470                 NdisFreeNetBufferListPool ( p_port->buf_mgr.h_send_pkt_pool );\r
1471 \r
1472         /* Destroy the receive packet and buffer pools. \r
1473         if( p_port->buf_mgr.h_buffer_pool )\r
1474                 NdisFreeBufferPool( p_port->buf_mgr.h_buffer_pool );*/\r
1475         if( p_port->buf_mgr.h_packet_pool )\r
1476                 NdisFreeNetBufferListPool ( p_port->buf_mgr.h_packet_pool );\r
1477 \r
1478         /* Free the receive and send descriptors. */\r
1479         cl_qpool_destroy( &p_port->buf_mgr.recv_pool );\r
1480 \r
1481         /* Free the lookaside list of scratch buffers. */\r
1482         NdisDeleteNPagedLookasideList( &p_port->buf_mgr.send_buf_list );\r
1483 \r
1484         IPOIB_EXIT(  IPOIB_DBG_INIT );\r
1485 }\r
1486 \r
1487 \r
1488 static cl_status_t\r
1489 __recv_ctor(\r
1490         IN                              void* const                                     p_object,\r
1491         IN                              void*                                           context,\r
1492                 OUT                     cl_pool_item_t** const          pp_pool_item )\r
1493 {\r
1494         ipoib_recv_desc_t       *p_desc;\r
1495         ipoib_port_t            *p_port;\r
1496 \r
1497 #if IPOIB_INLINE_RECV\r
1498         uint32_t                        ds0_len;\r
1499 #endif\r
1500 \r
1501         IPOIB_ENTER( IPOIB_DBG_ALLOC );\r
1502 \r
1503         CL_ASSERT( p_object );\r
1504         CL_ASSERT( context );\r
1505 \r
1506         p_desc = (ipoib_recv_desc_t*)p_object;\r
1507         p_port = (ipoib_port_t*)context;\r
1508 \r
1509         /* Setup the work request. */\r
1510         p_desc->wr.ds_array = p_desc->local_ds;\r
1511         p_desc->wr.wr_id = (uintn_t)p_desc;\r
1512 \r
1513 #if IPOIB_INLINE_RECV\r
1514         /* Sanity check on the receive buffer layout */\r
1515         CL_ASSERT( (void*)&p_desc->buf.eth.pkt.type ==\r
1516                 (void*)&p_desc->buf.ib.pkt.type );\r
1517         CL_ASSERT( sizeof(recv_buf_t) == sizeof(ipoib_pkt_t) + sizeof(ib_grh_t) );\r
1518 \r
1519         /* Setup the local data segment. */\r
1520         p_desc->local_ds[0].vaddr = cl_get_physaddr( &p_desc->buf );\r
1521         p_desc->local_ds[0].lkey = p_port->ib_mgr.lkey;\r
1522         ds0_len =\r
1523                 PAGE_SIZE - ((uint32_t)p_desc->local_ds[0].vaddr & (PAGE_SIZE - 1));\r
1524         if( ds0_len >= sizeof(recv_buf_t) )\r
1525         {\r
1526                 /* The whole buffer is within a page. */\r
1527                 p_desc->local_ds[0].length = ds0_len;\r
1528                 p_desc->wr.num_ds = 1;\r
1529         }\r
1530         else\r
1531         {\r
1532                 /* The buffer crosses page boundaries. */\r
1533                 p_desc->local_ds[0].length = ds0_len;\r
1534                 p_desc->local_ds[1].vaddr = cl_get_physaddr( \r
1535                         ((uint8_t*)&p_desc->buf) + ds0_len );\r
1536                 p_desc->local_ds[1].lkey = p_port->ib_mgr.lkey;\r
1537                 p_desc->local_ds[1].length = sizeof(recv_buf_t) - ds0_len;\r
1538                 p_desc->wr.num_ds = 2;\r
1539         }\r
1540 #else   /* IPOIB_INLINE_RECV */\r
1541         /* Allocate the receive buffer. */\r
1542         p_desc->p_buf = (recv_buf_t*)cl_zalloc( sizeof(recv_buf_t) );\r
1543         if( !p_desc->p_buf )\r
1544         {\r
1545                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1546                         ("Failed to allocate receive buffer.\n") );\r
1547                 return CL_INSUFFICIENT_MEMORY;\r
1548         }\r
1549 \r
1550         /* Sanity check on the receive buffer layout */\r
1551         CL_ASSERT( (void*)&p_desc->p_buf->eth.pkt.type ==\r
1552                 (void*)&p_desc->p_buf->ib.pkt.type );\r
1553 \r
1554         /* Setup the local data segment. */\r
1555         p_desc->local_ds[0].vaddr = cl_get_physaddr( p_desc->p_buf );\r
1556         p_desc->local_ds[0].length = sizeof(ipoib_pkt_t) + sizeof(ib_grh_t);\r
1557         p_desc->local_ds[0].lkey = p_port->ib_mgr.lkey;\r
1558         p_desc->wr.num_ds = 1;\r
1559 #endif  /* IPOIB_INLINE_RECV */\r
1560 \r
1561         *pp_pool_item = &p_desc->item;\r
1562 \r
1563         IPOIB_EXIT( IPOIB_DBG_ALLOC );\r
1564         return CL_SUCCESS;\r
1565 }\r
1566 \r
1567 \r
1568 #if !IPOIB_INLINE_RECV\r
1569 static void\r
1570 __recv_dtor(\r
1571         IN              const   cl_pool_item_t* const           p_pool_item,\r
1572         IN                              void                                            *context )\r
1573 {\r
1574         ipoib_recv_desc_t       *p_desc;\r
1575 \r
1576         IPOIB_ENTER(  IPOIB_DBG_ALLOC );\r
1577 \r
1578         UNUSED_PARAM( context );\r
1579 \r
1580         p_desc = PARENT_STRUCT( p_pool_item, ipoib_recv_desc_t, item );\r
1581 \r
1582         if( p_desc->p_buf )\r
1583                 cl_free( p_desc->p_buf );\r
1584 \r
1585         IPOIB_EXIT( IPOIB_DBG_ALLOC );\r
1586 }\r
1587 #endif\r
1588 \r
1589 \r
1590 static inline ipoib_recv_desc_t*\r
1591 __buf_mgr_get_recv(\r
1592         IN                              ipoib_port_t* const                     p_port )\r
1593 {\r
1594         ipoib_recv_desc_t       *p_desc;\r
1595         IPOIB_ENTER( IPOIB_DBG_RECV );\r
1596         p_desc = (ipoib_recv_desc_t*)cl_qpool_get( &p_port->buf_mgr.recv_pool );\r
1597         /* Reference the port object for the send. */\r
1598         if( p_desc )\r
1599         {\r
1600                 ipoib_port_ref( p_port, ref_get_recv );\r
1601                 CL_ASSERT( p_desc->wr.wr_id == (uintn_t)p_desc );\r
1602 #if IPOIB_INLINE_RECV\r
1603                 CL_ASSERT( p_desc->local_ds[0].vaddr ==\r
1604                         cl_get_physaddr( &p_desc->buf ) );\r
1605 #else   /* IPOIB_INLINE_RECV */\r
1606                 CL_ASSERT( p_desc->local_ds[0].vaddr ==\r
1607                         cl_get_physaddr( p_desc->p_buf ) );\r
1608                 CL_ASSERT( p_desc->local_ds[0].length ==\r
1609                         (sizeof(ipoib_pkt_t) + sizeof(ib_grh_t)) );\r
1610 #endif  /* IPOIB_INLINE_RECV */\r
1611                 CL_ASSERT( p_desc->local_ds[0].lkey == p_port->ib_mgr.lkey );\r
1612         }\r
1613         IPOIB_EXIT( IPOIB_DBG_RECV );\r
1614         return p_desc;\r
1615 }\r
1616 \r
1617 \r
1618 //NDIS60\r
1619 static inline void\r
1620 __buf_mgr_put_recv(\r
1621         IN                              ipoib_port_t* const                     p_port,\r
1622         IN                              ipoib_recv_desc_t* const        p_desc,\r
1623         IN                              NET_BUFFER_LIST* const          p_net_buffer_list OPTIONAL )\r
1624 {\r
1625         NET_BUFFER              *p_buf = NULL;\r
1626         MDL                             *p_mdl = NULL;\r
1627         IPOIB_ENTER(IPOIB_DBG_RECV );\r
1628 \r
1629         if( p_net_buffer_list )\r
1630         {\r
1631                 NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
1632                 p_buf = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list);\r
1633                 CL_ASSERT( p_buf );\r
1634                 p_mdl = NET_BUFFER_FIRST_MDL(p_buf);\r
1635                 CL_ASSERT( p_mdl );\r
1636                 NdisFreeMdl(p_mdl);\r
1637                 NdisFreeNetBufferList(p_net_buffer_list);\r
1638         }\r
1639 \r
1640         /* Return the descriptor to its pools. */\r
1641         cl_qpool_put( &p_port->buf_mgr.recv_pool, &p_desc->item );\r
1642 \r
1643         /*\r
1644          * Dereference the port object since the receive is no longer outstanding.\r
1645          */\r
1646         ipoib_port_deref( p_port, ref_get_recv );\r
1647         IPOIB_EXIT(  IPOIB_DBG_RECV );\r
1648 }\r
1649 \r
1650 \r
1651 static inline void\r
1652 __buf_mgr_put_recv_list(\r
1653         IN                              ipoib_port_t* const                     p_port,\r
1654         IN                              cl_qlist_t* const                       p_list )\r
1655 {\r
1656         //IPOIB_ENTER(  IPOIB_DBG_RECV );\r
1657         cl_qpool_put_list( &p_port->buf_mgr.recv_pool, p_list );\r
1658         //IPOIB_EXIT(  IPOIB_DBG_RECV );\r
1659 }\r
1660 \r
1661 \r
1662 static inline NET_BUFFER_LIST*\r
1663 __buf_mgr_get_NBL(\r
1664         IN                              ipoib_port_t* const                     p_port,\r
1665         IN                              ipoib_recv_desc_t* const        p_desc )\r
1666 {\r
1667         NET_BUFFER_LIST                 *p_net_buffer_list;\r
1668         MDL                                             *p_mdl;\r
1669 \r
1670         IPOIB_ENTER(  IPOIB_DBG_RECV );\r
1671 \r
1672         p_mdl = NdisAllocateMdl(p_port->p_adapter->h_adapter,\r
1673                                                         &p_desc->buf.eth.pkt,\r
1674                                                         p_desc->len );\r
1675         if( !p_mdl )\r
1676         {\r
1677                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1678                         ("Failed to allocate MDL\n") );\r
1679                 return NULL;\r
1680         }\r
1681 \r
1682         p_net_buffer_list = NdisAllocateNetBufferAndNetBufferList(\r
1683                                                 p_port->buf_mgr.h_packet_pool,\r
1684                                                 0,\r
1685                                                 0,\r
1686                                                 p_mdl,\r
1687                                                 0,\r
1688                                                 0);\r
1689 \r
1690         if( !p_net_buffer_list )\r
1691         {\r
1692                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1693                         ("Failed to allocate NET_BUFFER_LIST\n") );\r
1694                 NdisFreeMdl(p_mdl);\r
1695                 return NULL;\r
1696         }\r
1697 \r
1698         NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
1699         IPOIB_PORT_FROM_NBL( p_net_buffer_list ) = p_port;\r
1700         IPOIB_RECV_FROM_NBL( p_net_buffer_list ) = p_desc;\r
1701         p_net_buffer_list->SourceHandle = p_port->p_adapter->h_adapter;\r
1702 \r
1703         IPOIB_EXIT(  IPOIB_DBG_RECV );\r
1704         return p_net_buffer_list;\r
1705 }\r
1706 \r
1707 \r
1708 /******************************************************************************\r
1709 *\r
1710 * Receive manager implementation.\r
1711 *\r
1712 ******************************************************************************/\r
1713 static void\r
1714 __recv_mgr_construct(\r
1715         IN                              ipoib_port_t* const                     p_port )\r
1716 {\r
1717         IPOIB_ENTER( IPOIB_DBG_INIT );\r
1718 \r
1719         cl_qlist_init( &p_port->recv_mgr.done_list );\r
1720 \r
1721         p_port->recv_mgr.recv_NBL_array = NULL;\r
1722 \r
1723         IPOIB_EXIT( IPOIB_DBG_INIT );\r
1724 }\r
1725 \r
1726 \r
1727 static ib_api_status_t\r
1728 __recv_mgr_init(\r
1729         IN                              ipoib_port_t* const                     p_port )\r
1730 {\r
1731         IPOIB_ENTER( IPOIB_DBG_INIT );\r
1732 \r
1733         /* Allocate the NDIS_PACKET pointer array for indicating receives. */\r
1734         p_port->recv_mgr.recv_NBL_array = (NET_BUFFER_LIST **)cl_malloc(\r
1735                 sizeof(NET_BUFFER_LIST*) * p_port->p_adapter->params.rq_depth );\r
1736         if( !p_port->recv_mgr.recv_NBL_array )\r
1737         {\r
1738                 NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
1739                         EVENT_IPOIB_RECV_PKT_ARRAY, 0 );\r
1740                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1741                         ("cl_malloc for PNDIS_PACKET array failed.\n") );\r
1742                 return IB_INSUFFICIENT_MEMORY;\r
1743         }\r
1744 \r
1745         IPOIB_EXIT( IPOIB_DBG_INIT );\r
1746         return IB_SUCCESS;\r
1747 }\r
1748 \r
1749 \r
1750 static void\r
1751 __recv_mgr_destroy(\r
1752         IN                              ipoib_port_t* const                     p_port )\r
1753 {\r
1754         IPOIB_ENTER( IPOIB_DBG_INIT );\r
1755 \r
1756         CL_ASSERT( cl_is_qlist_empty( &p_port->recv_mgr.done_list ) );\r
1757         CL_ASSERT( !p_port->recv_mgr.depth );\r
1758 \r
1759         if( p_port->recv_mgr.recv_NBL_array )\r
1760                 cl_free( p_port->recv_mgr.recv_NBL_array );\r
1761 \r
1762         IPOIB_EXIT( IPOIB_DBG_INIT );\r
1763 }\r
1764 \r
1765 \r
1766 /*\r
1767  * Posts receive buffers to the receive queue and returns the number\r
1768  * of receives needed to bring the RQ to its low water mark.  Note\r
1769  * that the value is signed, and can go negative.  All tests must\r
1770  * be for > 0.\r
1771  */\r
1772 int32_t\r
1773 __recv_mgr_repost(\r
1774         IN                              ipoib_port_t* const                     p_port )\r
1775 {\r
1776         ipoib_recv_desc_t       *p_head = NULL, *p_tail = NULL, *p_next;\r
1777         ib_api_status_t         status;\r
1778         ib_recv_wr_t            *p_failed;\r
1779         PERF_DECLARE( GetRecv );\r
1780         PERF_DECLARE( PostRecv );\r
1781 \r
1782         IPOIB_ENTER( IPOIB_DBG_RECV );\r
1783 \r
1784         CL_ASSERT( p_port );\r
1785         cl_obj_lock( &p_port->obj );\r
1786         if( p_port->state != IB_QPS_RTS )\r
1787         {\r
1788                 cl_obj_unlock( &p_port->obj );\r
1789                 IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
1790                         ("Port in invalid state.  Not reposting.\n") );\r
1791                 return 0;\r
1792         }\r
1793         ipoib_port_ref( p_port, ref_repost );\r
1794         cl_obj_unlock( &p_port->obj );\r
1795 \r
1796         while( p_port->recv_mgr.depth < p_port->p_adapter->params.rq_depth )\r
1797         {\r
1798                 /* Pull receives out of the pool and chain them up. */\r
1799                 cl_perf_start( GetRecv );\r
1800                 p_next = __buf_mgr_get_recv( p_port );\r
1801                 cl_perf_stop( &p_port->p_adapter->perf, GetRecv );\r
1802                 if( !p_next )\r
1803                 {\r
1804                         IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_RECV,\r
1805                                 ("Out of receive descriptors! recv queue depth 0x%x\n",p_port->recv_mgr.depth) );\r
1806                         break;\r
1807                 }\r
1808 \r
1809                 if( !p_tail )\r
1810                 {\r
1811                         p_tail = p_next;\r
1812                         p_next->wr.p_next = NULL;\r
1813                 }\r
1814                 else\r
1815                 {\r
1816                         p_next->wr.p_next = &p_head->wr;\r
1817                 }\r
1818 \r
1819                 p_head = p_next;\r
1820 \r
1821                 p_port->recv_mgr.depth++;\r
1822         }\r
1823 \r
1824         if( p_head )\r
1825         {\r
1826                 cl_perf_start( PostRecv );\r
1827                 status = p_port->p_adapter->p_ifc->post_recv(\r
1828                         p_port->ib_mgr.h_qp, &p_head->wr, &p_failed );\r
1829                 cl_perf_stop( &p_port->p_adapter->perf, PostRecv );\r
1830 \r
1831                 if( status != IB_SUCCESS )\r
1832                 {\r
1833                         IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1834                                 ("ip_post_recv returned %s\n", \r
1835                                 p_port->p_adapter->p_ifc->get_err_str( status )) );\r
1836                         /* return the descriptors to the pool */\r
1837                         while( p_failed )\r
1838                         {\r
1839                                 p_head = PARENT_STRUCT( p_failed, ipoib_recv_desc_t, wr );\r
1840                                 p_failed = p_failed->p_next;\r
1841 \r
1842                                 __buf_mgr_put_recv( p_port, p_head, NULL );\r
1843                                 p_port->recv_mgr.depth--;\r
1844                         }\r
1845                 }\r
1846         }\r
1847 \r
1848         ipoib_port_deref( p_port, ref_repost );\r
1849         IPOIB_EXIT( IPOIB_DBG_RECV );\r
1850         return p_port->p_adapter->params.rq_low_watermark - p_port->recv_mgr.depth;\r
1851 }\r
1852 \r
1853 void\r
1854 ipoib_return_net_buffer_list(\r
1855         IN                              NDIS_HANDLE                                     adapter_context,\r
1856         IN                              NET_BUFFER_LIST                         *p_net_buffer_lists,\r
1857         IN                              ULONG                                           return_flags)\r
1858 {\r
1859         ipoib_port_t            *p_port;\r
1860         ipoib_recv_desc_t       *p_desc;\r
1861         NET_BUFFER_LIST         *cur_net_buffer_list,*next_net_buffer_list;\r
1862         int32_t                         shortage;\r
1863         \r
1864         PERF_DECLARE( ReturnPacket );\r
1865         PERF_DECLARE( ReturnPutRecv );\r
1866         PERF_DECLARE( ReturnRepostRecv );\r
1867         PERF_DECLARE( ReturnPreparePkt );\r
1868         PERF_DECLARE( ReturnNdisIndicate );\r
1869 \r
1870         IPOIB_ENTER( IPOIB_DBG_RECV );\r
1871 \r
1872         UNUSED_PARAM( return_flags );\r
1873 \r
1874         p_port = ((ipoib_adapter_t*)adapter_context)->p_port;\r
1875         CL_ASSERT( p_net_buffer_lists );\r
1876 \r
1877         cl_perf_start( ReturnPacket );\r
1878         cl_spinlock_acquire( &p_port->recv_lock );\r
1879         for (cur_net_buffer_list = p_net_buffer_lists;\r
1880                  cur_net_buffer_list != NULL;\r
1881                  cur_net_buffer_list = next_net_buffer_list)\r
1882         {\r
1883                 next_net_buffer_list = NET_BUFFER_LIST_NEXT_NBL(cur_net_buffer_list);\r
1884 \r
1885                 /* Get the port and descriptor from the NET_BUFFER_LIST. */\r
1886                 CL_ASSERT(p_port == IPOIB_PORT_FROM_NBL( cur_net_buffer_list ));\r
1887                 p_desc = IPOIB_RECV_FROM_NBL( cur_net_buffer_list );\r
1888 \r
1889                 \r
1890                 //TODO: NDIS60, rewrite this block\r
1891                 \r
1892 #if 0 //TODO CM flow\r
1893                 if( p_desc->type == PKT_TYPE_CM_UCAST )\r
1894                 {\r
1895                         int32_t                         discarded;\r
1896                         uint32_t                        NBL_cnt = 0;\r
1897                         \r
1898                         ib_api_status_t         status = IB_NOT_DONE;\r
1899 \r
1900                 \r
1901                         NDIS_BUFFER             *p_buf;\r
1902 \r
1903                         /* Unchain the NDIS buffer. */\r
1904                         NdisUnchainBufferAtFront( p_packet, &p_buf );\r
1905                         CL_ASSERT( p_buf );\r
1906                         /* Return the NDIS packet and NDIS buffer to their pools. */\r
1907                         NdisDprFreePacketNonInterlocked( p_packet );\r
1908                         NdisFreeBuffer( p_buf );\r
1909 \r
1910                         endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, (ipoib_cm_desc_t *)p_desc );\r
1911                         status = endpt_cm_post_recv( p_port );\r
1912                         if(  status != IB_SUCCESS )\r
1913                         {\r
1914                                 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
1915                                         ("Post Recv QP failed\n" ) );\r
1916                         }\r
1917                         cl_spinlock_release( &p_port->recv_lock );\r
1918                         return;\r
1919                 }\r
1920 #endif\r
1921 \r
1922                 cl_perf_start( ReturnPutRecv );\r
1923                 __buf_mgr_put_recv( p_port, p_desc, cur_net_buffer_list );\r
1924                 cl_perf_stop( &p_port->p_adapter->perf, ReturnPutRecv );\r
1925         }\r
1926 \r
1927 \r
1928 \r
1929         /* Repost buffers to HW */\r
1930         cl_perf_start( ReturnRepostRecv );\r
1931         shortage = __recv_mgr_repost( p_port );\r
1932         cl_perf_stop( &p_port->p_adapter->perf, ReturnRepostRecv );\r
1933         cl_spinlock_release( &p_port->recv_lock );\r
1934         cl_perf_stop( &p_port->p_adapter->perf, ReturnPacket );\r
1935 \r
1936         IPOIB_EXIT( IPOIB_DBG_RECV );\r
1937 }\r
1938 \r
1939 static void __recv_cb_dpc(KDPC *p_gc_dpc,void *context,void * s_arg1 , void * s_arg2)\r
1940 {\r
1941 \r
1942         ipoib_port_t *p_port = (ipoib_port_t *) context;\r
1943 \r
1944         UNREFERENCED_PARAMETER(p_gc_dpc);\r
1945         UNREFERENCED_PARAMETER(s_arg1);\r
1946         UNREFERENCED_PARAMETER(s_arg2);\r
1947 \r
1948 \r
1949         __recv_cb(NULL, p_port);\r
1950         ipoib_port_deref( p_port, ref_recv_cb );\r
1951 \r
1952 \r
1953 }\r
1954 \r
1955 \r
1956 static void\r
1957 __recv_cb(\r
1958         IN              const   ib_cq_handle_t                          h_cq,\r
1959         IN                              void                                            *cq_context )\r
1960 {\r
1961         ipoib_port_t            *p_port;\r
1962         ib_api_status_t         status;\r
1963         ib_wc_t                         wc[MAX_RECV_WC], *p_free, *p_wc;\r
1964         int32_t                         NBL_cnt, recv_cnt = 0, shortage, discarded;\r
1965         cl_qlist_t                      done_list, bad_list;\r
1966         size_t                          i;\r
1967         ULONG                           recv_complete_flags = 0;\r
1968 \r
1969         PERF_DECLARE( RecvCompBundle );\r
1970         PERF_DECLARE( RecvCb );\r
1971         PERF_DECLARE( PollRecv );\r
1972         PERF_DECLARE( RepostRecv );\r
1973         PERF_DECLARE( FilterRecv );\r
1974         PERF_DECLARE( BuildNBLArray );\r
1975         PERF_DECLARE( RecvNdisIndicate );\r
1976         PERF_DECLARE( RearmRecv );\r
1977         PERF_DECLARE( PutRecvList );\r
1978 \r
1979         IPOIB_ENTER( IPOIB_DBG_RECV );\r
1980 \r
1981         cl_perf_clr( RecvCompBundle );\r
1982 \r
1983         cl_perf_start( RecvCb );\r
1984 \r
1985         UNUSED_PARAM( h_cq );\r
1986 \r
1987         NDIS_SET_SEND_COMPLETE_FLAG(recv_complete_flags, NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL );\r
1988 \r
1989         p_port = (ipoib_port_t*)cq_context;\r
1990 \r
1991         cl_qlist_init( &done_list );\r
1992         cl_qlist_init( &bad_list );\r
1993 \r
1994         ipoib_port_ref( p_port, ref_recv_cb );\r
1995         for( i = 0; i < MAX_RECV_WC; i++ )\r
1996                 wc[i].p_next = &wc[i + 1];\r
1997         wc[MAX_RECV_WC - 1].p_next = NULL;\r
1998 \r
1999         /*\r
2000          * We'll be accessing the endpoint map so take a reference\r
2001          * on it to prevent modifications.\r
2002          */\r
2003         cl_obj_lock( &p_port->obj );\r
2004         cl_atomic_inc( &p_port->endpt_rdr );\r
2005         cl_obj_unlock( &p_port->obj );\r
2006 \r
2007         do\r
2008         {\r
2009                 /* If we get here, then the list of WCs is intact. */\r
2010                 p_free = wc;\r
2011 \r
2012                 cl_perf_start( PollRecv );\r
2013                 status = p_port->p_adapter->p_ifc->poll_cq(\r
2014                         p_port->ib_mgr.h_recv_cq, &p_free, &p_wc );\r
2015                 cl_perf_stop( &p_port->p_adapter->perf, PollRecv );\r
2016                 CL_ASSERT( status == IB_SUCCESS || status == IB_NOT_FOUND );\r
2017 \r
2018                 /* Look at the payload now and filter ARP and DHCP packets. */\r
2019                 cl_perf_start( FilterRecv );\r
2020                 recv_cnt += __recv_mgr_filter( p_port, p_wc, &done_list, &bad_list );\r
2021                 cl_perf_stop( &p_port->p_adapter->perf, FilterRecv );\r
2022 \r
2023         } while( ( !p_free ) && ( recv_cnt < 16 )); //TODO restore back to 128\r
2024 \r
2025         /* We're done looking at the endpoint map, release the reference. */\r
2026         cl_atomic_dec( &p_port->endpt_rdr );\r
2027 \r
2028         cl_perf_log( &p_port->p_adapter->perf, RecvCompBundle, recv_cnt );\r
2029 \r
2030         cl_spinlock_acquire( &p_port->recv_lock );\r
2031 \r
2032         /* Update our posted depth. */\r
2033         p_port->recv_mgr.depth -= recv_cnt;\r
2034 \r
2035         /* Return any discarded receives to the pool */\r
2036         cl_perf_start( PutRecvList );\r
2037         __buf_mgr_put_recv_list( p_port, &bad_list );\r
2038         cl_perf_stop( &p_port->p_adapter->perf, PutRecvList );\r
2039 \r
2040         do\r
2041         {\r
2042                 //int32_t cnt;\r
2043                 /* Repost ASAP so we don't starve the RQ. */\r
2044                 cl_perf_start( RepostRecv );\r
2045                 shortage = __recv_mgr_repost( p_port );\r
2046                 \r
2047                 if( shortage > 0 )\r
2048                 {                               \r
2049                         recv_complete_flags |= NDIS_RECEIVE_FLAGS_RESOURCES;\r
2050                         cl_dbg_out("Got SHORTAGE=%d\n",shortage);\r
2051                 }\r
2052                 \r
2053                 cl_perf_stop( &p_port->p_adapter->perf, RepostRecv );\r
2054 \r
2055                 cl_perf_start( BuildNBLArray );\r
2056                 /* Notify NDIS of any and all possible receive buffers. */\r
2057                 NBL_cnt = __recv_mgr_build_NBL_array(\r
2058                         p_port, &done_list, &discarded);\r
2059                 cl_perf_stop( &p_port->p_adapter->perf, BuildNBLArray );\r
2060 \r
2061                 /* Only indicate receives if we actually had any. */\r
2062                 if( discarded && shortage > 0 )\r
2063                 {\r
2064                         /* We may have thrown away packets, and have a shortage */\r
2065                         cl_perf_start( RepostRecv );\r
2066                         __recv_mgr_repost( p_port );\r
2067                         cl_perf_stop( &p_port->p_adapter->perf, RepostRecv );\r
2068                 }\r
2069 \r
2070                 if( !NBL_cnt ) {\r
2071                         //cl_dbg_out("NBL cnt == 0 :-(\n");\r
2072                         break;\r
2073                 }\r
2074 \r
2075                 cl_spinlock_release( &p_port->recv_lock );\r
2076 \r
2077                 cl_perf_start( RecvNdisIndicate );\r
2078                 \r
2079                 NdisMIndicateReceiveNetBufferLists(\r
2080                         p_port->p_adapter->h_adapter,\r
2081                         p_port->recv_mgr.recv_NBL_array[0],\r
2082                         NDIS_DEFAULT_PORT_NUMBER,\r
2083                         NBL_cnt,\r
2084                         recv_complete_flags);\r
2085 \r
2086                 cl_perf_stop( &p_port->p_adapter->perf, RecvNdisIndicate );\r
2087 \r
2088                 /*\r
2089                  * Cap the number of receives to put back to what we just indicated\r
2090                  * with NDIS_STATUS_RESOURCES.\r
2091                  */\r
2092                 if( shortage > 0 )\r
2093                 {\r
2094 \r
2095                         cl_dbg_out("GOT SHORTAGE <===============\n");\r
2096                         /* Return all but the last packet to the pool. */\r
2097                         cl_spinlock_acquire( &p_port->recv_lock );\r
2098                         //while( shortage-- > 1 )\r
2099                         while ( NBL_cnt-- > 0)\r
2100                         {\r
2101                                 __buf_mgr_put_recv( p_port,\r
2102                                         (ipoib_recv_desc_t *)IPOIB_RECV_FROM_NBL( p_port->recv_mgr.recv_NBL_array[NBL_cnt] ),\r
2103                                         p_port->recv_mgr.recv_NBL_array[NBL_cnt] );\r
2104                         }\r
2105                         __recv_mgr_repost( p_port );\r
2106                         cl_spinlock_release( &p_port->recv_lock );\r
2107 \r
2108                         /*\r
2109                          * Return the last packet as if NDIS returned it, so that we repost\r
2110                          * and report any other pending receives.\r
2111                          */\r
2112                         //ipoib_return_net_buffer_list( p_port, p_port->recv_mgr.recv_NBL_array[0],recv_complete_flags );\r
2113                 }\r
2114                 cl_spinlock_acquire( &p_port->recv_lock );\r
2115 \r
2116         } while( NBL_cnt );\r
2117         cl_spinlock_release( &p_port->recv_lock );\r
2118 \r
2119         if (p_free ) {\r
2120                 /*\r
2121                  * Rearm after filtering to prevent contention on the enpoint maps\r
2122                  * and eliminate the possibility of having a call to\r
2123                  * __endpt_mgr_insert find a duplicate.\r
2124                  */\r
2125                 cl_perf_start( RearmRecv );\r
2126                 status = p_port->p_adapter->p_ifc->rearm_cq(\r
2127                         p_port->ib_mgr.h_recv_cq, FALSE );\r
2128                 cl_perf_stop( &p_port->p_adapter->perf, RearmRecv );\r
2129                 CL_ASSERT( status == IB_SUCCESS );\r
2130 \r
2131                 ipoib_port_deref( p_port, ref_recv_cb );\r
2132         } else {\r
2133                 // Please note the reference is still up\r
2134                 KeInsertQueueDpc(&p_port->recv_dpc, NULL, NULL);\r
2135         }\r
2136 \r
2137         cl_perf_stop( &p_port->p_adapter->perf, RecvCb );\r
2138 \r
2139         IPOIB_EXIT( IPOIB_DBG_RECV );\r
2140 }\r
2141 \r
2142 \r
2143 static void\r
2144 __recv_get_endpts(\r
2145         IN                              ipoib_port_t* const                     p_port,\r
2146         IN                              ipoib_recv_desc_t* const        p_desc,\r
2147         IN                              ib_wc_t* const                          p_wc,\r
2148                 OUT                     ipoib_endpt_t** const           pp_src,\r
2149                 OUT                     ipoib_endpt_t** const           pp_dst )\r
2150 {\r
2151         ib_api_status_t         status;\r
2152         mac_addr_t                      mac;\r
2153         PERF_DECLARE( GetEndptByGid );\r
2154         PERF_DECLARE( GetEndptByLid );\r
2155         PERF_DECLARE( EndptInsert );\r
2156 \r
2157         IPOIB_ENTER( IPOIB_DBG_RECV );\r
2158 \r
2159         /* Setup our shortcut pointers based on whether GRH is valid. */\r
2160         if( p_wc->recv.ud.recv_opt & IB_RECV_OPT_GRH_VALID )\r
2161         {\r
2162                 /* Lookup the source endpoints based on GID. */\r
2163                 cl_perf_start( GetEndptByGid );\r
2164                 *pp_src =\r
2165 #if IPOIB_INLINE_RECV\r
2166                         __endpt_mgr_get_by_gid( p_port, &p_desc->buf.ib.grh.src_gid );\r
2167 #else   /* IPOIB_INLINE_RECV */\r
2168                         __endpt_mgr_get_by_gid( p_port, &p_desc->p_buf->ib.grh.src_gid );\r
2169 #endif  /* IPOIB_INLINE_RECV */\r
2170                 cl_perf_stop( &p_port->p_adapter->perf, GetEndptByGid );\r
2171 \r
2172                 /*\r
2173                  * Lookup the destination endpoint based on GID.\r
2174                  * This is used along with the packet filter to determine\r
2175                  * whether to report this to NDIS.\r
2176                  */\r
2177                 cl_perf_start( GetEndptByGid );\r
2178                 *pp_dst =\r
2179 #if IPOIB_INLINE_RECV\r
2180                         __endpt_mgr_get_by_gid( p_port, &p_desc->buf.ib.grh.dest_gid );\r
2181 #else   /* IPOIB_INLINE_RECV */\r
2182                         __endpt_mgr_get_by_gid( p_port, &p_desc->p_buf->ib.grh.dest_gid );\r
2183 #endif  /* IPOIB_INLINE_RECV */\r
2184                 cl_perf_stop( &p_port->p_adapter->perf, GetEndptByGid );\r
2185 \r
2186                 /*\r
2187                  * Create the source endpoint if it does not exist.  Note that we\r
2188                  * can only do this for globally routed traffic since we need the\r
2189                  * information from the GRH to generate the MAC.\r
2190                  */\r
2191                 if( !*pp_src )\r
2192                 {\r
2193                         status = ipoib_mac_from_guid(\r
2194 #if IPOIB_INLINE_RECV\r
2195                                 p_desc->buf.ib.grh.src_gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, &mac );\r
2196 #else   /* IPOIB_INLINE_RECV */\r
2197                                 p_desc->p_buf->ib.grh.src_gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, &mac );\r
2198 #endif  /* IPOIB_INLINE_RECV */\r
2199                         if( status != IB_SUCCESS )\r
2200                         {\r
2201                                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2202                                         ("ipoib_mac_from_guid returned %s\n",\r
2203                                         p_port->p_adapter->p_ifc->get_err_str( status )) );\r
2204                                 return;\r
2205                         }\r
2206 \r
2207                         /* Create the endpoint. */\r
2208 #if IPOIB_INLINE_RECV\r
2209                         *pp_src = ipoib_endpt_create( &p_desc->buf.ib.grh.src_gid,\r
2210 #else   /* IPOIB_INLINE_RECV */\r
2211                         *pp_src = ipoib_endpt_create( &p_desc->p_buf->ib.grh.src_gid,\r
2212 #endif  /* IPOIB_INLINE_RECV */\r
2213                                 p_wc->recv.ud.remote_lid, p_wc->recv.ud.remote_qp );\r
2214                         if( !*pp_src )\r
2215                         {\r
2216                                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2217                                         ("ipoib_endpt_create failed\n") );\r
2218                                 return;\r
2219                         }\r
2220                         cl_perf_start( EndptInsert );\r
2221                         cl_obj_lock( &p_port->obj );\r
2222                         status = __endpt_mgr_insert( p_port, mac, *pp_src );\r
2223                         if( status != IB_SUCCESS )\r
2224                         {\r
2225                                 cl_obj_unlock( &p_port->obj );\r
2226                                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2227                                         ("__endpt_mgr_insert returned %s\n",\r
2228                                         p_port->p_adapter->p_ifc->get_err_str( status )) );\r
2229                                 *pp_src = NULL;\r
2230                                 return;\r
2231                         }\r
2232                         cl_obj_unlock( &p_port->obj );\r
2233                         cl_perf_stop( &p_port->p_adapter->perf, EndptInsert );\r
2234                 }\r
2235         }\r
2236         else\r
2237         {\r
2238                 /*\r
2239                  * Lookup the remote endpoint based on LID.  Note that only\r
2240                  * unicast traffic can be LID routed.\r
2241                  */\r
2242                 cl_perf_start( GetEndptByLid );\r
2243                 *pp_src = __endpt_mgr_get_by_lid( p_port, p_wc->recv.ud.remote_lid );\r
2244                 cl_perf_stop( &p_port->p_adapter->perf, GetEndptByLid );\r
2245                 *pp_dst = p_port->p_local_endpt;\r
2246                 CL_ASSERT( *pp_dst );\r
2247         }\r
2248 \r
2249         if( *pp_src && !ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) &&\r
2250                 (*pp_src)->qpn != p_wc->recv.ud.remote_qp )\r
2251         {\r
2252                 /* Update the QPN for the endpoint. */\r
2253                 IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
2254                         ("Updating QPN for MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",\r
2255                         (*pp_src )->mac.addr[0], (*pp_src )->mac.addr[1],\r
2256                         (*pp_src )->mac.addr[2], (*pp_src )->mac.addr[3],\r
2257                         (*pp_src )->mac.addr[4], (*pp_src )->mac.addr[5]) );\r
2258 //              (*pp_src)->qpn = p_wc->recv.ud.remote_qp;\r
2259         }\r
2260 \r
2261         if( *pp_src && *pp_dst )\r
2262         {\r
2263                 IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_RECV,\r
2264                         ("Recv:\n"\r
2265                         "\tsrc MAC: %02X-%02X-%02X-%02X-%02X-%02X\n"\r
2266                         "\tdst MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",\r
2267                         (*pp_src )->mac.addr[0], (*pp_src )->mac.addr[1],\r
2268                         (*pp_src )->mac.addr[2], (*pp_src )->mac.addr[3],\r
2269                         (*pp_src )->mac.addr[4], (*pp_src )->mac.addr[5],\r
2270                         (*pp_dst )->mac.addr[0], (*pp_dst )->mac.addr[1],\r
2271                         (*pp_dst )->mac.addr[2], (*pp_dst )->mac.addr[3],\r
2272                         (*pp_dst )->mac.addr[4], (*pp_dst )->mac.addr[5]) );\r
2273         }\r
2274 \r
2275         IPOIB_EXIT( IPOIB_DBG_RECV );\r
2276 }\r
2277 \r
2278 \r
2279 static int32_t\r
2280 __recv_mgr_filter(\r
2281         IN                              ipoib_port_t* const                     p_port,\r
2282         IN                              ib_wc_t* const                          p_done_wc_list,\r
2283                 OUT                     cl_qlist_t* const                       p_done_list,\r
2284                 OUT                     cl_qlist_t* const                       p_bad_list )\r
2285 {\r
2286         ipoib_recv_desc_t               *p_desc;\r
2287         ib_wc_t                                 *p_wc;\r
2288         ipoib_pkt_t                             *p_ipoib;\r
2289         eth_pkt_t                               *p_eth;\r
2290         ipoib_endpt_t                   *p_src, *p_dst;\r
2291         ib_api_status_t                 status;\r
2292         uint32_t                                len;\r
2293         int32_t                                 recv_cnt = 0;\r
2294         PERF_DECLARE( GetRecvEndpts );\r
2295         PERF_DECLARE( RecvGen );\r
2296         PERF_DECLARE( RecvTcp );\r
2297         PERF_DECLARE( RecvUdp );\r
2298         PERF_DECLARE( RecvDhcp );\r
2299         PERF_DECLARE( RecvArp );\r
2300 \r
2301         IPOIB_ENTER( IPOIB_DBG_RECV );\r
2302 \r
2303         for( p_wc = p_done_wc_list; p_wc; p_wc = p_wc->p_next )\r
2304         {\r
2305                 CL_ASSERT( p_wc->status != IB_WCS_SUCCESS || p_wc->wc_type == IB_WC_RECV );\r
2306                 p_desc = (ipoib_recv_desc_t*)(uintn_t)p_wc->wr_id;\r
2307                 recv_cnt++;\r
2308 \r
2309                 if( p_wc->status != IB_WCS_SUCCESS )\r
2310                 {\r
2311                         if( p_wc->status != IB_WCS_WR_FLUSHED_ERR )\r
2312                         {\r
2313                                 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2314                                         ("Failed completion %s  (vendor specific %#x)\n",\r
2315                                         p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status ),\r
2316                                         (int)p_wc->vendor_specific) );\r
2317                                 ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
2318                         }\r
2319                         else\r
2320                         {\r
2321                                 IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_RECV,\r
2322                                         ("Flushed completion %s\n",\r
2323                                         p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status )) );\r
2324                                 ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_DROPPED, 0, 0 );\r
2325                         }\r
2326                         cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
2327                         /* Dereference the port object on behalf of the failed receive. */\r
2328                         ipoib_port_deref( p_port, ref_failed_recv_wc );\r
2329                         continue;\r
2330                 }\r
2331 \r
2332                 len = p_wc->length - sizeof(ib_grh_t);\r
2333 \r
2334                 if( len < sizeof(ipoib_hdr_t) )\r
2335                 {\r
2336                         IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2337                                 ("Received ETH packet < min size\n") );\r
2338                         ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
2339                         cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
2340                         ipoib_port_deref( p_port, ref_recv_inv_len );\r
2341                         continue;\r
2342                 }\r
2343 \r
2344                 if((len - sizeof(ipoib_hdr_t)) > p_port->p_adapter->params.payload_mtu)\r
2345                 {\r
2346                         IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2347                                 ("Received ETH packet len %d > payload MTU (%d)\n",\r
2348                                 (len - sizeof(ipoib_hdr_t)),\r
2349                                 p_port->p_adapter->params.payload_mtu) );\r
2350                         ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
2351                         cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
2352                         ipoib_port_deref( p_port, ref_recv_inv_len );\r
2353                         continue;\r
2354                         \r
2355                 }\r
2356                 /* Successful completion.  Get the receive information. */\r
2357                 p_desc->ndis_csum.Value = ( ( p_wc->recv.ud.recv_opt & IB_RECV_OPT_CSUM_MASK ) >> 8 );\r
2358                 p_desc->len = len + 14 - 4 ;\r
2359                 cl_perf_start( GetRecvEndpts );\r
2360                 __recv_get_endpts( p_port, p_desc, p_wc, &p_src, &p_dst );\r
2361                 cl_perf_stop( &p_port->p_adapter->perf, GetRecvEndpts );\r
2362 \r
2363 #if IPOIB_INLINE_RECV\r
2364                 p_ipoib = &p_desc->buf.ib.pkt;\r
2365                 p_eth = &p_desc->buf.eth.pkt;\r
2366 #else   /* IPOIB_INLINE_RECV */\r
2367                 p_ipoib = &p_desc->p_buf->ib.pkt;\r
2368                 p_eth = &p_desc->p_buf->eth.pkt;\r
2369 #endif  /*IPOIB_INLINE_RECV */\r
2370 \r
2371                 if( p_src )\r
2372                 {\r
2373                         /* Don't report loopback traffic - we requested SW loopback. */\r
2374                         if( !cl_memcmp( &p_port->p_adapter->params.conf_mac,\r
2375                                 &p_src->mac, sizeof(p_port->p_adapter->params.conf_mac) ) )\r
2376                         {\r
2377                                 /*\r
2378                                  * "This is not the packet you're looking for" - don't update\r
2379                                  * receive statistics, the packet never happened.\r
2380                                  */\r
2381                                 cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
2382                                 /* Dereference the port object on behalf of the failed recv. */\r
2383                                 ipoib_port_deref( p_port, ref_recv_loopback );\r
2384                                 continue;\r
2385                         }\r
2386                 }\r
2387 \r
2388                 switch( p_ipoib->hdr.type )\r
2389                 {\r
2390                 case ETH_PROT_TYPE_IP:\r
2391                         if( len < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t)) )\r
2392                         {\r
2393                                 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2394                                         ("Received IP packet < min size\n") );\r
2395                                 status = IB_INVALID_SETTING;\r
2396                                 break;\r
2397                         }\r
2398 \r
2399                         if( p_ipoib->type.ip.hdr.offset ||\r
2400                                 p_ipoib->type.ip.hdr.prot != IP_PROT_UDP )\r
2401                         {\r
2402                                 /* Unfiltered.  Setup the ethernet header and report. */\r
2403                                 cl_perf_start( RecvTcp );\r
2404                                 status = __recv_gen( p_ipoib, p_eth, p_src, p_dst );\r
2405                                 cl_perf_stop( &p_port->p_adapter->perf, RecvTcp );\r
2406                                 break;\r
2407                         }\r
2408 \r
2409                         /* First packet of a UDP transfer. */\r
2410                         if( len <\r
2411                                 (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t) + sizeof(udp_hdr_t)) )\r
2412                         {\r
2413                                 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2414                                         ("Received UDP packet < min size\n") );\r
2415                                 status = IB_INVALID_SETTING;\r
2416                                 break;\r
2417                         }\r
2418 \r
2419                         /* Check if DHCP conversion is required. */\r
2420                         if( (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_SERVER &&\r
2421                                 p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_CLIENT) ||\r
2422                                 (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_CLIENT &&\r
2423                                 p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_SERVER)||\r
2424                                 (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_PROXY_SERVER &&\r
2425                                 p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_CLIENT) ||\r
2426                                 (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_CLIENT &&\r
2427                                 p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_PROXY_SERVER))\r
2428                         {\r
2429                                 if( len < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t) +\r
2430                                         sizeof(udp_hdr_t) + DHCP_MIN_SIZE) )\r
2431                                 {\r
2432                                         IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2433                                                 ("Received DHCP < min size\n") );\r
2434                                         status = IB_INVALID_SETTING;\r
2435                                         break;\r
2436                                 }\r
2437                                 if ((p_ipoib->type.ip.hdr.ver_hl & 0x0f) != 5 ) {\r
2438                                         // If there are IP options in this message, we are in trouble in any case\r
2439                                         status = IB_INVALID_SETTING;\r
2440                                         break;                                  \r
2441                                 }\r
2442                                 /* UDP packet with BOOTP ports in src/dst port numbers. */\r
2443                                 cl_perf_start( RecvDhcp );\r
2444                                 status = __recv_dhcp( p_port, p_ipoib, p_eth, p_src, p_dst );\r
2445                                 cl_perf_stop( &p_port->p_adapter->perf, RecvDhcp );\r
2446                         }\r
2447                         else\r
2448                         {\r
2449                                 /* Unfiltered.  Setup the ethernet header and report. */\r
2450                                 cl_perf_start( RecvUdp );\r
2451                                 status = __recv_gen( p_ipoib, p_eth, p_src, p_dst );\r
2452                                 cl_perf_stop( &p_port->p_adapter->perf, RecvUdp );\r
2453                         }\r
2454                         break;\r
2455 \r
2456                 case ETH_PROT_TYPE_ARP:\r
2457                         if( len < (sizeof(ipoib_hdr_t) + sizeof(ipoib_arp_pkt_t)) )\r
2458                         {\r
2459                                 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2460                                         ("Received ARP < min size\n") );\r
2461                                 status = IB_INVALID_SETTING;\r
2462                                 break;\r
2463                         }\r
2464                         cl_perf_start( RecvArp );\r
2465                         status = __recv_arp( p_port, p_wc, p_ipoib, p_eth, &p_src, p_dst );\r
2466                         cl_perf_stop( &p_port->p_adapter->perf, RecvArp );\r
2467                         len = sizeof(ipoib_hdr_t) + sizeof(arp_pkt_t);\r
2468                         break;\r
2469 \r
2470                 default:\r
2471                         /* Unfiltered.  Setup the ethernet header and report. */\r
2472                         cl_perf_start( RecvGen );\r
2473                         status = __recv_gen( p_ipoib, p_eth, p_src, p_dst );\r
2474                         cl_perf_stop( &p_port->p_adapter->perf, RecvGen );\r
2475                 }\r
2476 \r
2477                 if( status != IB_SUCCESS )\r
2478                 {\r
2479                         /* Update stats. */\r
2480                         ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
2481                         cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
2482                         /* Dereference the port object on behalf of the failed receive. */\r
2483                         ipoib_port_deref( p_port, ref_recv_filter );\r
2484                 }\r
2485                 else\r
2486                 {\r
2487                         ip_stat_sel_t               ip_stat;\r
2488                         p_desc->len =\r
2489                                 len + sizeof(eth_hdr_t) - sizeof(ipoib_hdr_t);\r
2490                         if( p_dst->h_mcast)\r
2491                         {\r
2492                                 if( p_dst->dgid.multicast.raw_group_id[10] == 0xFF &&\r
2493                                         p_dst->dgid.multicast.raw_group_id[11] == 0xFF &&\r
2494                                         p_dst->dgid.multicast.raw_group_id[12] == 0xFF &&\r
2495                                         p_dst->dgid.multicast.raw_group_id[13] == 0xFF )\r
2496                                 {\r
2497                                         p_desc->type = PKT_TYPE_BCAST;\r
2498                                         ip_stat = IP_STAT_BCAST_BYTES;\r
2499                                 }\r
2500                                 else\r
2501                                 {\r
2502                                         p_desc->type = PKT_TYPE_MCAST;\r
2503                                         ip_stat = IP_STAT_MCAST_BYTES;\r
2504                                 }\r
2505                         }\r
2506                         else\r
2507                         {\r
2508                                 p_desc->type = PKT_TYPE_UCAST;\r
2509                                 ip_stat = IP_STAT_UCAST_BYTES;\r
2510                                 \r
2511                         }\r
2512                         cl_qlist_insert_tail( p_done_list, &p_desc->item.list_item );\r
2513                         ipoib_inc_recv_stat( p_port->p_adapter, ip_stat, len, 1 );  \r
2514                 }\r
2515         }\r
2516 \r
2517         IPOIB_EXIT( IPOIB_DBG_RECV );\r
2518         return recv_cnt;\r
2519 }\r
2520 \r
2521 \r
2522 static ib_api_status_t\r
2523 __recv_gen(\r
2524         IN              const   ipoib_pkt_t* const                      p_ipoib,\r
2525                 OUT                     eth_pkt_t* const                        p_eth,\r
2526         IN                              ipoib_endpt_t* const            p_src,\r
2527         IN                              ipoib_endpt_t* const            p_dst )\r
2528 {\r
2529         IPOIB_ENTER( IPOIB_DBG_RECV );\r
2530 \r
2531         if( !p_src || !p_dst )\r
2532         {\r
2533                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2534                         ("Received packet with no matching endpoints.\n") );\r
2535                 return IB_NOT_DONE;\r
2536         }\r
2537 \r
2538         /*\r
2539          * Fill in the ethernet header.  Note that doing so will overwrite\r
2540          * the IPoIB header, so start by moving the information from the IPoIB\r
2541          * header.\r
2542          */\r
2543         p_eth->hdr.type = p_ipoib->hdr.type;\r
2544         p_eth->hdr.src = p_src->mac;\r
2545         p_eth->hdr.dst = p_dst->mac;\r
2546 \r
2547         if ( p_eth->hdr.dst.addr[0] == 1 && \r
2548                  p_eth->hdr.type == ETH_PROT_TYPE_IP &&\r
2549                  p_eth->hdr.dst.addr[2] == 0x5E)  \r
2550         {\r
2551                 p_eth->hdr.dst.addr[1] = 0;\r
2552                 p_eth->hdr.dst.addr[3] = p_eth->hdr.dst.addr[3] & 0x7f;\r
2553         }\r
2554         if (p_dst->h_mcast)\r
2555                 p_dst->is_in_use = TRUE;\r
2556 \r
2557         IPOIB_EXIT( IPOIB_DBG_RECV );\r
2558         return IB_SUCCESS;\r
2559 }\r
2560 \r
2561 \r
2562 static ib_api_status_t\r
2563 __recv_dhcp(\r
2564         IN                              ipoib_port_t* const                     p_port,\r
2565         IN              const   ipoib_pkt_t* const                      p_ipoib,\r
2566                 OUT                     eth_pkt_t* const                        p_eth,\r
2567         IN                              ipoib_endpt_t* const            p_src,\r
2568         IN                              ipoib_endpt_t* const            p_dst )\r
2569 {\r
2570         ib_api_status_t         status;\r
2571         dhcp_pkt_t                      *p_dhcp;\r
2572         uint8_t                         *p_option;\r
2573         uint8_t                         *p_cid = NULL;\r
2574         uint8_t                         msg = 0;\r
2575 \r
2576         IPOIB_ENTER( IPOIB_DBG_RECV );\r
2577 \r
2578         UNUSED_PARAM( p_port );\r
2579 \r
2580         /* Create the ethernet header. */\r
2581         status = __recv_gen( p_ipoib, p_eth, p_src, p_dst );\r
2582         if( status != IB_SUCCESS )\r
2583         {\r
2584                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2585                         ("__recv_gen returned %s.\n", \r
2586                         p_port->p_adapter->p_ifc->get_err_str( status )) );\r
2587                 return status;\r
2588         }\r
2589 \r
2590         /* Fixup the payload. */\r
2591         p_dhcp = &p_eth->type.ip.prot.udp.dhcp;\r
2592         if( p_dhcp->op != DHCP_REQUEST && p_dhcp->op != DHCP_REPLY )\r
2593         {\r
2594                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2595                         ("Invalid DHCP op code.\n") );\r
2596                 return IB_INVALID_SETTING;\r
2597         }\r
2598 \r
2599         /*\r
2600          * Find the client identifier option, making sure to skip\r
2601          * the "magic cookie".\r
2602          */\r
2603         p_option = &p_dhcp->options[0];\r
2604         if ( *(uint32_t *)p_option != DHCP_COOKIE )\r
2605         {\r
2606                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2607                         ("DHCP cookie corrupted.\n") );\r
2608                 return IB_INVALID_PARAMETER;\r
2609         }\r
2610 \r
2611         p_option = &p_dhcp->options[DHCP_COOKIE_SIZE];\r
2612         while( *p_option != DHCP_OPT_END && p_option < &p_dhcp->options[312] )\r
2613         {\r
2614                 switch( *p_option )\r
2615                 {\r
2616                 case DHCP_OPT_PAD:\r
2617                         p_option++;\r
2618                         break;\r
2619 \r
2620                 case DHCP_OPT_MSG:\r
2621                         msg = p_option[2];\r
2622                         p_option += 3;\r
2623                         break;\r
2624 \r
2625                 case DHCP_OPT_CLIENT_ID:\r
2626                         p_cid = p_option;\r
2627                         /* Fall through. */\r
2628 \r
2629                 default:\r
2630                         /*\r
2631                          * All other options have a length byte following the option code.\r
2632                          * Offset by the length to get to the next option.\r
2633                          */\r
2634                         p_option += (p_option[1] + 2);\r
2635                 }\r
2636         }\r
2637 \r
2638         switch( msg )\r
2639         {\r
2640         /* message from client */\r
2641         case DHCPDISCOVER:\r
2642         case DHCPREQUEST:\r
2643         case DHCPDECLINE:\r
2644         case DHCPRELEASE:\r
2645         case DHCPINFORM:\r
2646                 if( !p_cid )\r
2647                 {\r
2648                         IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2649                                 ("Failed to find required Client-identifier option.\n") );\r
2650                         return IB_INVALID_SETTING;\r
2651                 }\r
2652                 if( p_dhcp->htype != DHCP_HW_TYPE_IB )\r
2653                 {\r
2654                         IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2655                                 ("Invalid hardware address type.\n") );\r
2656                         return IB_INVALID_SETTING;\r
2657                 }\r
2658                 break;\r
2659         /* message from DHCP server */\r
2660         case DHCPOFFER:\r
2661         case DHCPACK:\r
2662         case DHCPNAK:\r
2663                 break;\r
2664 \r
2665         default:\r
2666                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2667                         ("Invalide message type.\n") );\r
2668                 return IB_INVALID_PARAMETER;\r
2669         }\r
2670         p_eth->type.ip.prot.udp.hdr.chksum = 0;\r
2671         p_dhcp->htype = DHCP_HW_TYPE_ETH;\r
2672         p_dhcp->hlen = HW_ADDR_LEN;\r
2673 \r
2674         if( p_cid ) /* from client */\r
2675         {\r
2676                 /* Validate that the length and type of the option is as required. */\r
2677                 if( p_cid[1] != 21 )\r
2678                 {\r
2679                         IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2680                                 ("Client-identifier length not 21 as required.\n") );\r
2681                         return IB_INVALID_SETTING;\r
2682                 }\r
2683                 if( p_cid[2] != DHCP_HW_TYPE_IB )\r
2684                 {\r
2685                         IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2686                                 ("Client-identifier type is wrong.\n") );\r
2687                         return IB_INVALID_SETTING;\r
2688                 }\r
2689                 /*\r
2690                  * Copy the GID value from the option so that we can make aligned\r
2691                  * accesses to the contents.\r
2692                  * Recover CID to standard type.\r
2693                  */\r
2694                 p_cid[1] =  sizeof (ib_net64_t) + 1;// CID length \r
2695                 p_cid[2] =  DHCP_HW_TYPE_ETH;// CID type\r
2696                 RtlMoveMemory( &p_cid[3], &p_cid[15], sizeof (ib_net64_t) );\r
2697                 RtlFillMemory(&p_cid[11], 12, 0);\r
2698 \r
2699                 RtlCopyMemory( p_dhcp->chaddr, &p_src->mac, sizeof(p_src->mac) );\r
2700                 RtlFillMemory( &p_dhcp->chaddr[sizeof(p_src->mac)],\r
2701                                ( sizeof(p_dhcp->chaddr) - sizeof(p_src->mac) ), 0 );\r
2702         }\r
2703         IPOIB_EXIT( IPOIB_DBG_RECV );\r
2704         return status;\r
2705 }\r
2706 \r
2707 \r
2708 static ib_api_status_t\r
2709 __recv_arp(\r
2710         IN                              ipoib_port_t* const                     p_port,\r
2711         IN                              ib_wc_t* const                          p_wc,\r
2712         IN              const   ipoib_pkt_t* const                      p_ipoib,\r
2713                 OUT                     eth_pkt_t* const                        p_eth,\r
2714         IN                              ipoib_endpt_t** const           pp_src,\r
2715         IN                              ipoib_endpt_t* const            p_dst )\r
2716 {\r
2717         ib_api_status_t                 status;\r
2718         arp_pkt_t                               *p_arp;\r
2719         const ipoib_arp_pkt_t   *p_ib_arp;\r
2720         ib_gid_t                                gid;\r
2721         mac_addr_t                              mac;\r
2722         ipoib_hw_addr_t                 null_hw = {0};\r
2723         uint8_t                                 cm_capable = 0;\r
2724 \r
2725         IPOIB_ENTER( IPOIB_DBG_RECV );\r
2726 \r
2727         if( !p_dst )\r
2728         {\r
2729                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2730                         ("Unknown destination endpoint\n") );\r
2731                 return IB_INVALID_SETTING;\r
2732         }\r
2733 \r
2734         p_ib_arp = &p_ipoib->type.arp;\r
2735         p_arp = &p_eth->type.arp;\r
2736 \r
2737         if( p_ib_arp->hw_type != ARP_HW_TYPE_IB )\r
2738         {\r
2739                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2740                         ("ARP hardware type is not IB\n") );\r
2741                 return IB_INVALID_SETTING;\r
2742         }\r
2743 \r
2744         if( p_ib_arp->hw_size != sizeof(ipoib_hw_addr_t) )\r
2745         {\r
2746                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2747                         ("ARP hardware address size is not sizeof(ipoib_hw_addr_t)\n") );\r
2748                 return IB_INVALID_SETTING;\r
2749         }\r
2750 \r
2751         if( p_ib_arp->prot_type != ETH_PROT_TYPE_IP )\r
2752         {\r
2753                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2754                         ("ARP protocal type not IP\n") );\r
2755                 return IB_INVALID_SETTING;\r
2756         }\r
2757 \r
2758         cm_capable = ipoib_addr_get_flags( &p_ib_arp->src_hw );\r
2759 \r
2760         /*\r
2761          * If we don't have a source, lookup the endpoint specified in the payload.\r
2762          */\r
2763         if( !*pp_src )\r
2764                 *pp_src = __endpt_mgr_get_by_gid( p_port, &p_ib_arp->src_hw.gid );\r
2765 \r
2766         /*\r
2767          * If the endpoint exists for the GID, make sure\r
2768          * the dlid and qpn match the arp.\r
2769          */\r
2770         if( *pp_src )\r
2771         {\r
2772                 if( cl_memcmp( &(*pp_src)->dgid, &p_ib_arp->src_hw.gid,\r
2773                         sizeof(ib_gid_t) ) )\r
2774                 {\r
2775                         /*\r
2776                          * GIDs for the endpoint are different.  The ARP must\r
2777                          * have been proxied.  Dereference it.\r
2778                          */\r
2779                         *pp_src = NULL;\r
2780                 }\r
2781                 else if( (*pp_src)->dlid &&\r
2782                         (*pp_src)->dlid != p_wc->recv.ud.remote_lid )\r
2783                 {\r
2784                         /* Out of date!  Destroy the endpoint and replace it. */\r
2785                         __endpt_mgr_remove( p_port, *pp_src );\r
2786                         *pp_src = NULL;\r
2787                 }\r
2788                 else if ( ! ((*pp_src)->dlid)) {\r
2789                         /* Out of date!  Destroy the endpoint and replace it. */\r
2790                         __endpt_mgr_remove( p_port, *pp_src );\r
2791                         *pp_src = NULL;\r
2792                 }\r
2793                 else if( ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) )\r
2794                 {\r
2795                         if( (*pp_src)->qpn != ipoib_addr_get_qpn( &p_ib_arp->src_hw ) &&\r
2796                                  p_wc->recv.ud.remote_qp !=     ipoib_addr_get_qpn( &p_ib_arp->src_hw ) )\r
2797                         {\r
2798                                 /* Out of date!  Destroy the endpoint and replace it. */\r
2799                                 __endpt_mgr_remove( p_port, *pp_src );\r
2800                                 *pp_src = NULL;\r
2801                         }\r
2802                 }\r
2803                 else if( (*pp_src)->qpn != p_wc->recv.ud.remote_qp )\r
2804                 {\r
2805                         /* Out of date!  Destroy the endpoint and replace it. */\r
2806                         __endpt_mgr_remove( p_port, *pp_src );\r
2807                         *pp_src = NULL;\r
2808                 }\r
2809         }\r
2810 \r
2811         /* Do we need to create an endpoint for this GID? */\r
2812         if( !*pp_src )\r
2813         {\r
2814                 /* Copy the src GID to allow aligned access */\r
2815                 cl_memcpy( &gid, &p_ib_arp->src_hw.gid, sizeof(ib_gid_t) );\r
2816                 status = ipoib_mac_from_guid( gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, &mac );\r
2817                 if (status == IB_INVALID_GUID_MASK)\r
2818                 {\r
2819                         IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR,\r
2820                                 ("Invalid GUID mask received, rejecting it") );\r
2821                         ipoib_create_log(p_port->p_adapter->h_adapter, GUID_MASK_LOG_INDEX, EVENT_IPOIB_WRONG_PARAMETER_WRN);\r
2822                 }\r
2823                 else if( status != IB_SUCCESS )\r
2824                 {\r
2825                         IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2826                                 ("ipoib_mac_from_guid returned %s\n",\r
2827                                 p_port->p_adapter->p_ifc->get_err_str( status )) );\r
2828                         return status;\r
2829                 }\r
2830                 /*\r
2831                  * Create the endpoint.\r
2832                  */\r
2833                 *pp_src = ipoib_endpt_create( &p_ib_arp->src_hw.gid,\r
2834                         p_wc->recv.ud.remote_lid, ipoib_addr_get_qpn( &p_ib_arp->src_hw ) );\r
2835 \r
2836                 if( !*pp_src )\r
2837                 {\r
2838                         IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2839                                 ("ipoib_endpt_create failed\n") );\r
2840                         return status;\r
2841                 }\r
2842 \r
2843                 cl_obj_lock( &p_port->obj );\r
2844                 status = __endpt_mgr_insert( p_port, mac, *pp_src );\r
2845                 if( status != IB_SUCCESS )\r
2846                 {\r
2847                         cl_obj_unlock( &p_port->obj );\r
2848                         IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2849                                 ("__endpt_mgr_insert return %s \n",\r
2850                                 p_port->p_adapter->p_ifc->get_err_str( status )) );\r
2851                         return status;\r
2852                 }\r
2853 \r
2854                 cl_obj_unlock( &p_port->obj );\r
2855         }\r
2856 \r
2857         (*pp_src)->cm_flag = cm_capable;\r
2858 \r
2859         CL_ASSERT( !cl_memcmp(\r
2860                 &(*pp_src)->dgid, &p_ib_arp->src_hw.gid, sizeof(ib_gid_t) ) );\r
2861         CL_ASSERT( ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) ||\r
2862                 (*pp_src)->qpn == ipoib_addr_get_qpn( &p_ib_arp->src_hw ) );\r
2863 #if 0\r
2864         if( p_port->p_adapter->params.cm_enabled &&\r
2865                 p_ib_arp->op == ARP_OP_REQ &&\r
2866                 cm_capable == IPOIB_CM_FLAG_RC )\r
2867         {\r
2868                 /* if we've got ARP request and RC flag is set, \r
2869                 save SID for connect REQ to be sent in ARP reply\r
2870                 when requestor's path get resolved */\r
2871                 if( endpt_cm_get_state( (*pp_src) ) == IPOIB_CM_DISCONNECTED )\r
2872                 {\r
2873                         (*pp_src)->cm_flag = cm_capable;\r
2874                         ipoib_addr_set_sid( \r
2875                                 &(*pp_src)->conn.service_id,\r
2876                                 ipoib_addr_get_qpn( &p_ib_arp->src_hw ) );\r
2877                 }\r
2878         }\r
2879 #endif\r
2880 #if 0 //DBG\r
2881         if( p_port->p_adapter->params.cm_enabled )\r
2882         {\r
2883                 IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
2884                         (" ARP %s from ENDPT[%p] state %d CM cap: %d QPN: %#x MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",\r
2885                         ((p_ib_arp->op == ARP_OP_REQ )? "REQUEST" : "REPLY"),\r
2886                         *pp_src, endpt_cm_get_state( *pp_src ), \r
2887                         ((cm_capable == IPOIB_CM_FLAG_RC)? 1: 0),\r
2888                         cl_ntoh32( ipoib_addr_get_qpn( &p_ib_arp->src_hw ) ),\r
2889                         (*pp_src)->mac.addr[0], (*pp_src)->mac.addr[1],\r
2890                         (*pp_src)->mac.addr[2], (*pp_src)->mac.addr[3],\r
2891                         (*pp_src)->mac.addr[4], (*pp_src)->mac.addr[5] ));\r
2892         }\r
2893 #endif\r
2894 \r
2895         /* Now swizzle the data. */\r
2896         p_arp->hw_type = ARP_HW_TYPE_ETH;\r
2897         p_arp->hw_size = sizeof(mac_addr_t);\r
2898         p_arp->src_hw = (*pp_src)->mac;\r
2899         p_arp->src_ip = p_ib_arp->src_ip;\r
2900 \r
2901         if( cl_memcmp( &p_ib_arp->dst_hw, &null_hw, sizeof(ipoib_hw_addr_t) ) )\r
2902         {\r
2903                 if( cl_memcmp( &p_dst->dgid, &p_ib_arp->dst_hw.gid, sizeof(ib_gid_t) ) )\r
2904                 {\r
2905                         /*\r
2906                          * We received bcast ARP packet that means\r
2907                          * remote port lets everyone know it was changed IP/MAC\r
2908                          * or just activated\r
2909                          */\r
2910 \r
2911                         /* Guy: TODO: Check why this check fails in case of Voltaire IPR */\r
2912 \r
2913                         if ( !ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) &&\r
2914                                  !ib_gid_is_multicast( (const ib_gid_t*)&p_dst->dgid ) )\r