removed Revison keyword since ID keyword exists, deleted unused files
[mirror/winof/.git] / ulp / ipoib / kernel / ipoib_endpoint.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  *\r
4  * This software is available to you under the OpenIB.org BSD license\r
5  * below:\r
6  *\r
7  *     Redistribution and use in source and binary forms, with or\r
8  *     without modification, are permitted provided that the following\r
9  *     conditions are met:\r
10  *\r
11  *      - Redistributions of source code must retain the above\r
12  *        copyright notice, this list of conditions and the following\r
13  *        disclaimer.\r
14  *\r
15  *      - Redistributions in binary form must reproduce the above\r
16  *        copyright notice, this list of conditions and the following\r
17  *        disclaimer in the documentation and/or other materials\r
18  *        provided with the distribution.\r
19  *\r
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
24  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
25  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
26  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
27  * SOFTWARE.\r
28  *\r
29  * $Id$\r
30  */\r
31 \r
32 \r
33 \r
34 #include "ipoib_endpoint.h"\r
35 #include "ipoib_port.h"\r
36 #include "ipoib_debug.h"\r
37 #include <complib/cl_atomic.h>\r
38 \r
39 \r
40 static void\r
41 __endpt_destroying(\r
42         IN                              cl_obj_t*                                       p_obj );\r
43 \r
44 static void\r
45 __endpt_cleanup(\r
46         IN                              cl_obj_t*                                       p_obj );\r
47 \r
48 static void\r
49 __endpt_free(\r
50         IN                              cl_obj_t*                                       p_obj );\r
51 \r
52 static ib_api_status_t\r
53 __create_mcast_av(\r
54         IN                              ib_pd_handle_t                          h_pd,\r
55         IN                              uint8_t                                         port_num,\r
56         IN                              ib_member_rec_t* const          p_member_rec,\r
57                 OUT                     ib_av_handle_t* const           ph_av );\r
58 \r
59 static inline ipoib_port_t*\r
60 __endpt_parent(\r
61         IN                              ipoib_endpt_t* const            p_endpt );\r
62 \r
63 static void\r
64 __path_query_cb(\r
65         IN                              ib_query_rec_t                          *p_query_rec );\r
66 \r
67 static void\r
68 __endpt_resolve(\r
69         IN                              ipoib_endpt_t* const            p_endpt );\r
70 \r
71 \r
72 ipoib_endpt_t*\r
73 ipoib_endpt_create(\r
74         IN              const   ib_gid_t* const                         p_dgid,\r
75         IN              const   net16_t                                         dlid,\r
76         IN              const   net32_t                                         qpn )\r
77 {\r
78         ipoib_endpt_t   *p_endpt;\r
79         cl_status_t             status;\r
80 \r
81         IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
82 \r
83         p_endpt = cl_zalloc( sizeof(ipoib_endpt_t) );\r
84         if( !p_endpt )\r
85         {\r
86                 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,\r
87                         ("Failed to allocate endpoint (%d bytes)\n",\r
88                         sizeof(ipoib_endpt_t)) );\r
89                 return NULL;\r
90         }\r
91 \r
92         cl_obj_construct( &p_endpt->obj, IPOIB_OBJ_ENDPOINT );\r
93 \r
94         status = cl_obj_init( &p_endpt->obj, CL_DESTROY_ASYNC,\r
95                 __endpt_destroying, __endpt_cleanup, __endpt_free );\r
96 \r
97         p_endpt->dgid = *p_dgid;\r
98         p_endpt->dlid = dlid;\r
99         p_endpt->qpn = qpn;\r
100 \r
101         IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
102         return p_endpt;\r
103 }\r
104 \r
105 \r
106 static ib_api_status_t\r
107 __create_mcast_av(\r
108         IN                              ib_pd_handle_t                          h_pd,\r
109         IN                              uint8_t                                         port_num,\r
110         IN                              ib_member_rec_t* const          p_member_rec,\r
111                 OUT                     ib_av_handle_t* const           ph_av )\r
112 {\r
113         ib_av_attr_t    av_attr;\r
114         uint32_t                flow_lbl;\r
115         uint8_t                 hop_lmt;\r
116         ib_api_status_t status;\r
117         ipoib_endpt_t   *p_endpt;\r
118 \r
119         IPOIB_ENTER( IPOIB_DBG_MCAST );\r
120 \r
121         p_endpt = PARENT_STRUCT(ph_av, ipoib_endpt_t, h_av );\r
122 \r
123         cl_memclr( &av_attr, sizeof(ib_av_attr_t) );\r
124         av_attr.port_num = port_num;\r
125         ib_member_get_sl_flow_hop( p_member_rec->sl_flow_hop,\r
126                 &av_attr.sl, &flow_lbl, &hop_lmt );\r
127         av_attr.dlid = p_member_rec->mlid;\r
128         av_attr.grh_valid = TRUE;\r
129         av_attr.grh.hop_limit = hop_lmt;\r
130         av_attr.grh.dest_gid = p_member_rec->mgid;\r
131         av_attr.grh.src_gid = p_member_rec->port_gid;\r
132         av_attr.grh.ver_class_flow =\r
133                 ib_grh_set_ver_class_flow( 6, p_member_rec->tclass, flow_lbl );\r
134         av_attr.static_rate = p_member_rec->rate & IB_PATH_REC_BASE_MASK;\r
135         av_attr.path_bits = 0;\r
136         /* port is not attached to endpoint at this point, so use endpt ifc reference */\r
137         status = p_endpt->p_ifc->create_av( h_pd, &av_attr, ph_av );\r
138 \r
139         if( status != IB_SUCCESS )\r
140         {\r
141                 IPOIB_TRACE( IPOIB_DBG_ERROR,\r
142                         ("ib_create_av returned %s\n",\r
143                         p_endpt->p_ifc->get_err_str( status )) );\r
144         }\r
145 \r
146         IPOIB_EXIT( IPOIB_DBG_MCAST );\r
147         return status;\r
148 }\r
149 \r
150 \r
151 ib_api_status_t\r
152 ipoib_endpt_set_mcast(\r
153         IN                              ipoib_endpt_t* const            p_endpt,\r
154         IN                              ib_pd_handle_t                          h_pd,\r
155         IN                              uint8_t                                         port_num,\r
156         IN                              ib_mcast_rec_t* const           p_mcast_rec )\r
157 {\r
158         ib_api_status_t status;\r
159 \r
160         IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
161 \r
162         status = __create_mcast_av( h_pd, port_num, p_mcast_rec->p_member_rec,\r
163                 &p_endpt->h_av );\r
164         if( status != IB_SUCCESS )\r
165         {\r
166                 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,\r
167                         ("__create_mcast_av returned %s\n", \r
168                         p_endpt->p_ifc->get_err_str( status )) );\r
169                 return status;\r
170         }\r
171         p_endpt->h_mcast = p_mcast_rec->h_mcast;\r
172 \r
173         IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
174         return IB_SUCCESS;\r
175 }\r
176 \r
177 \r
178 static void\r
179 __endpt_destroying(\r
180         IN                              cl_obj_t*                                       p_obj )\r
181 {\r
182         ipoib_endpt_t   *p_endpt;\r
183         ipoib_port_t    *p_port;\r
184 \r
185         IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
186 \r
187         p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj );\r
188         p_port = __endpt_parent( p_endpt );\r
189 \r
190         cl_obj_lock( p_obj );\r
191         if( p_endpt->h_query )\r
192         {\r
193                 p_port->p_adapter->p_ifc->cancel_query(\r
194                         p_port->p_adapter->h_al, p_endpt->h_query );\r
195                 p_endpt->h_query = NULL;\r
196         }\r
197         cl_obj_unlock( p_obj );\r
198         \r
199         IPOIB_EXIT( IPOIB_DBG_INIT );\r
200 }\r
201 \r
202 \r
203 static void\r
204 __endpt_cleanup(\r
205         IN                              cl_obj_t*                                       p_obj )\r
206 {\r
207         ipoib_endpt_t   *p_endpt;\r
208         ipoib_port_t    *p_port;\r
209 \r
210         IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
211 \r
212         p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj );\r
213         p_port = __endpt_parent( p_endpt );\r
214 \r
215         /* Resume sends so that any pending sends for this endpoint fail. */\r
216         ipoib_port_resume( p_port );\r
217 \r
218         /* Leave the multicast group if it exists. */\r
219         if( p_endpt->h_mcast )\r
220         {\r
221                 IPOIB_TRACE( IPOIB_DBG_INFO, ("Leaving MCast group\n") );\r
222                 p_port->p_adapter->p_ifc->leave_mcast( p_endpt->h_mcast, NULL );\r
223         }\r
224 \r
225         /* Destroy the AV if it exists. */\r
226         if( p_endpt->h_av )\r
227                 p_port->p_adapter->p_ifc->destroy_av( p_endpt->h_av );\r
228 \r
229         IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
230 }\r
231 \r
232 \r
233 static void\r
234 __endpt_free(\r
235         IN                              cl_obj_t*                                       p_obj )\r
236 {\r
237         ipoib_endpt_t   *p_endpt;\r
238 \r
239         IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
240 \r
241         p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj );\r
242 \r
243         cl_obj_deinit( p_obj );\r
244         cl_free( p_endpt );\r
245 \r
246         IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
247 }\r
248 \r
249 \r
250 static inline ipoib_port_t*\r
251 __endpt_parent(\r
252         IN                              ipoib_endpt_t* const            p_endpt )\r
253 {\r
254         return PARENT_STRUCT( p_endpt->rel.p_parent_obj, ipoib_port_t, obj );\r
255 }\r
256 \r
257 \r
258 /*\r
259  * This function is called with the port object's send lock held and\r
260  * a reference held on the endpoint.  If we fail, we release the reference.\r
261  */\r
262 NDIS_STATUS\r
263 ipoib_endpt_queue(\r
264         IN                              ipoib_endpt_t* const            p_endpt )\r
265 {\r
266         ib_api_status_t status;\r
267         ipoib_port_t    *p_port;\r
268         ib_query_req_t  query;\r
269         ib_user_query_t info;\r
270         ib_path_rec_t   path;\r
271 \r
272         IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
273 \r
274         if( p_endpt->h_av )\r
275         {\r
276                 IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
277                 return NDIS_STATUS_SUCCESS;\r
278         }\r
279 \r
280         if( p_endpt->h_query )\r
281         {\r
282                 ipoib_endpt_deref( p_endpt );\r
283                 IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
284                 return NDIS_STATUS_PENDING;\r
285         }\r
286 \r
287         /* This is the first packet for this endpoint.  Query the SA. */\r
288         p_port = __endpt_parent( p_endpt );\r
289 \r
290         IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
291 \r
292         info.method = IB_MAD_METHOD_GETTABLE;\r
293         info.attr_id = IB_MAD_ATTR_PATH_RECORD;\r
294         info.attr_size = sizeof(ib_path_rec_t);\r
295         info.comp_mask = IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID |\r
296                 IB_PR_COMPMASK_REVERSIBLE | IB_PR_COMPMASK_NUM_PATH;\r
297         info.p_attr = &path;\r
298 \r
299         cl_memclr( &path, sizeof(ib_path_rec_t) );\r
300         path.dgid = p_endpt->dgid;\r
301         ib_gid_set_default( &path.sgid, p_port->p_adapter->guids.port_guid );\r
302         path.num_path = 0x1;\r
303 \r
304         cl_memclr( &query, sizeof(ib_query_req_t) );\r
305         query.query_type = IB_QUERY_USER_DEFINED;\r
306         query.p_query_input = &info;\r
307         query.port_guid = p_port->p_adapter->guids.port_guid;\r
308         query.timeout_ms = p_port->p_adapter->params.sa_timeout;\r
309         query.retry_cnt = p_port->p_adapter->params.sa_retry_cnt;\r
310 \r
311         query.query_context = p_endpt;\r
312         query.pfn_query_cb = __path_query_cb;\r
313 \r
314         status = p_port->p_adapter->p_ifc->query(\r
315                 p_port->p_adapter->h_al, &query, &p_endpt->h_query );\r
316         if( status != IB_SUCCESS )\r
317         {\r
318                 IPOIB_TRACE( IPOIB_DBG_ERROR,\r
319                         ("ib_query for path returned %s\n", \r
320                         p_port->p_adapter->p_ifc->get_err_str( status )) );\r
321                 ipoib_endpt_deref( p_endpt );\r
322                 /* Flag the adapter as hung. */\r
323                 p_port->p_adapter->hung = TRUE;\r
324         }\r
325 \r
326         IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
327         return NDIS_STATUS_PENDING;\r
328 }\r
329 \r
330 \r
331 static void\r
332 __path_query_cb(\r
333         IN                              ib_query_rec_t                          *p_query_rec )\r
334 {\r
335         ib_api_status_t status;\r
336         ipoib_endpt_t   *p_endpt;\r
337         ipoib_port_t    *p_port;\r
338         ib_av_attr_t    av_attr;\r
339         ib_path_rec_t   *p_path;\r
340         net32_t                 flow_lbl;\r
341 \r
342         IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
343 \r
344         p_endpt = (ipoib_endpt_t*__ptr64)p_query_rec->query_context;\r
345         p_port = __endpt_parent( p_endpt );\r
346 \r
347         cl_obj_lock( &p_endpt->obj );\r
348         p_endpt->h_query = NULL;\r
349         if( p_endpt->obj.state == CL_DESTROYING )\r
350         {\r
351                 cl_obj_unlock( &p_endpt->obj );\r
352                 ipoib_endpt_deref( p_endpt );\r
353                 if( p_query_rec->p_result_mad )\r
354                         p_port->p_adapter->p_ifc->put_mad( p_query_rec->p_result_mad );\r
355                 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,\r
356                         ("Endpoint destroying, aborting.\n") );\r
357                 return;\r
358         }\r
359         cl_obj_unlock( &p_endpt->obj );\r
360 \r
361         if( p_query_rec->status != IB_SUCCESS )\r
362         {\r
363                 p_port->p_adapter->hung = TRUE;\r
364                 ipoib_endpt_deref( p_endpt );\r
365                 if( p_query_rec->p_result_mad )\r
366                         p_port->p_adapter->p_ifc->put_mad( p_query_rec->p_result_mad );\r
367                 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,\r
368                         ("Path query failed with %s\n",\r
369                         p_port->p_adapter->p_ifc->get_err_str( p_query_rec->status )) );\r
370                 return;\r
371         }\r
372 \r
373         p_path = ib_get_query_path_rec( p_query_rec->p_result_mad, 0 );\r
374 \r
375         cl_memclr( &av_attr, sizeof(ib_av_attr_t) );\r
376 \r
377         av_attr.port_num = p_port->port_num;\r
378 \r
379         av_attr.sl = ib_path_rec_sl( p_path );\r
380         av_attr.dlid = p_path->dlid;\r
381 \r
382         if( p_path->dgid.unicast.prefix != IB_DEFAULT_SUBNET_PREFIX )\r
383         {\r
384                 flow_lbl = ib_path_rec_flow_lbl( p_path );\r
385                 /* Not on the same subnet, need GRH. */\r
386                 av_attr.grh_valid = TRUE;\r
387                 av_attr.grh.ver_class_flow = ib_grh_set_ver_class_flow(\r
388                         6, p_path->tclass, flow_lbl );\r
389                 av_attr.grh.resv1 = 0;\r
390                 av_attr.grh.resv2 = 0;\r
391                 av_attr.grh.hop_limit = ib_path_rec_hop_limit( p_path );\r
392                 av_attr.grh.src_gid = p_path->sgid;\r
393                 av_attr.grh.dest_gid = p_path->dgid;\r
394         }\r
395         else if( !p_endpt->dlid )\r
396         {\r
397                 /* This is a subnet local endpoint that does not have its LID set. */\r
398                 p_endpt->dlid = p_path->dlid;\r
399                 /*\r
400                  * Insert the item in the LID map so that locally routed unicast\r
401                  * traffic will resolve it properly.\r
402                  */\r
403                 cl_obj_lock( &p_port->obj );\r
404                 cl_qmap_insert( &p_port->endpt_mgr.lid_endpts,\r
405                         p_endpt->dlid, &p_endpt->lid_item );\r
406                 cl_obj_unlock( &p_port->obj );\r
407         }\r
408         av_attr.static_rate = ib_path_rec_rate( p_path );\r
409         av_attr.path_bits = 0;\r
410 \r
411         /* Done with the path record.  Release the MAD. */\r
412         p_port->p_adapter->p_ifc->put_mad( p_query_rec->p_result_mad );\r
413 \r
414         /* Create the AV. */\r
415         status = p_port->p_adapter->p_ifc->create_av(\r
416                 p_port->ib_mgr.h_pd, &av_attr, &p_endpt->h_av );\r
417         if( status != IB_SUCCESS )\r
418         {\r
419                 p_port->p_adapter->hung = TRUE;\r
420                 ipoib_endpt_deref( p_endpt );\r
421                 cl_obj_unlock( &p_endpt->obj );\r
422                 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,\r
423                         ("ib_create_av failed with %s\n", \r
424                         p_port->p_adapter->p_ifc->get_err_str( status )) );\r
425                 return;\r
426         }\r
427 \r
428         /* Try to send all pending sends. */\r
429         ipoib_port_resume( p_port );\r
430 \r
431         /* Release the reference taken for the SA query. */\r
432         ipoib_endpt_deref( p_endpt );\r
433         IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
434 }\r