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