2 * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.
\r
4 * This software is available to you under the OpenIB.org BSD license
\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
11 * - Redistributions of source code must retain the above
\r
12 * copyright notice, this list of conditions and the following
\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
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
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
42 IN cl_obj_t* p_obj );
\r
46 IN cl_obj_t* p_obj );
\r
50 IN cl_obj_t* p_obj );
\r
52 static ib_api_status_t
\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
59 static inline ipoib_port_t*
\r
61 IN ipoib_endpt_t* const p_endpt );
\r
65 IN ib_query_rec_t *p_query_rec );
\r
69 IN ipoib_endpt_t* const p_endpt );
\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
78 ipoib_endpt_t *p_endpt;
\r
81 IPOIB_ENTER( IPOIB_DBG_ENDPT );
\r
83 p_endpt = cl_zalloc( sizeof(ipoib_endpt_t) );
\r
86 IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,
\r
87 ("Failed to allocate endpoint (%d bytes)\n",
\r
88 sizeof(ipoib_endpt_t)) );
\r
92 cl_obj_construct( &p_endpt->obj, IPOIB_OBJ_ENDPOINT );
\r
94 status = cl_obj_init( &p_endpt->obj, CL_DESTROY_ASYNC,
\r
95 __endpt_destroying, __endpt_cleanup, __endpt_free );
\r
97 p_endpt->dgid = *p_dgid;
\r
98 p_endpt->dlid = dlid;
\r
101 IPOIB_EXIT( IPOIB_DBG_ENDPT );
\r
106 static ib_api_status_t
\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
113 ib_av_attr_t av_attr;
\r
116 ib_api_status_t status;
\r
117 ipoib_endpt_t *p_endpt;
\r
119 IPOIB_ENTER( IPOIB_DBG_MCAST );
\r
121 p_endpt = PARENT_STRUCT(ph_av, ipoib_endpt_t, h_av );
\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
139 if( status != IB_SUCCESS )
\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
146 IPOIB_EXIT( IPOIB_DBG_MCAST );
\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
158 ib_api_status_t status;
\r
160 IPOIB_ENTER( IPOIB_DBG_ENDPT );
\r
162 status = __create_mcast_av( h_pd, port_num, p_mcast_rec->p_member_rec,
\r
164 if( status != IB_SUCCESS )
\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
171 p_endpt->h_mcast = p_mcast_rec->h_mcast;
\r
173 IPOIB_EXIT( IPOIB_DBG_ENDPT );
\r
179 __endpt_destroying(
\r
180 IN cl_obj_t* p_obj )
\r
182 ipoib_endpt_t *p_endpt;
\r
183 ipoib_port_t *p_port;
\r
185 IPOIB_ENTER( IPOIB_DBG_ENDPT );
\r
187 p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj );
\r
188 p_port = __endpt_parent( p_endpt );
\r
190 cl_obj_lock( p_obj );
\r
191 if( p_endpt->h_query )
\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
197 cl_obj_unlock( p_obj );
\r
199 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
205 IN cl_obj_t* p_obj )
\r
207 ipoib_endpt_t *p_endpt;
\r
208 ipoib_port_t *p_port;
\r
210 IPOIB_ENTER( IPOIB_DBG_ENDPT );
\r
212 p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj );
\r
213 p_port = __endpt_parent( p_endpt );
\r
215 /* Resume sends so that any pending sends for this endpoint fail. */
\r
216 ipoib_port_resume( p_port );
\r
218 /* Leave the multicast group if it exists. */
\r
219 if( p_endpt->h_mcast )
\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
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
229 IPOIB_EXIT( IPOIB_DBG_ENDPT );
\r
235 IN cl_obj_t* p_obj )
\r
237 ipoib_endpt_t *p_endpt;
\r
239 IPOIB_ENTER( IPOIB_DBG_ENDPT );
\r
241 p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj );
\r
243 cl_obj_deinit( p_obj );
\r
244 cl_free( p_endpt );
\r
246 IPOIB_EXIT( IPOIB_DBG_ENDPT );
\r
250 static inline ipoib_port_t*
\r
252 IN ipoib_endpt_t* const p_endpt )
\r
254 return PARENT_STRUCT( p_endpt->rel.p_parent_obj, ipoib_port_t, obj );
\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
264 IN ipoib_endpt_t* const p_endpt )
\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
272 IPOIB_ENTER( IPOIB_DBG_ENDPT );
\r
274 if( p_endpt->h_av )
\r
276 IPOIB_EXIT( IPOIB_DBG_ENDPT );
\r
277 return NDIS_STATUS_SUCCESS;
\r
280 if( p_endpt->h_query )
\r
282 ipoib_endpt_deref( p_endpt );
\r
283 IPOIB_EXIT( IPOIB_DBG_ENDPT );
\r
284 return NDIS_STATUS_PENDING;
\r
287 /* This is the first packet for this endpoint. Query the SA. */
\r
288 p_port = __endpt_parent( p_endpt );
\r
290 IPOIB_ENTER( IPOIB_DBG_ENDPT );
\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
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
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
311 query.query_context = p_endpt;
\r
312 query.pfn_query_cb = __path_query_cb;
\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
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
326 IPOIB_EXIT( IPOIB_DBG_ENDPT );
\r
327 return NDIS_STATUS_PENDING;
\r
333 IN ib_query_rec_t *p_query_rec )
\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
342 IPOIB_ENTER( IPOIB_DBG_ENDPT );
\r
344 p_endpt = (ipoib_endpt_t*__ptr64)p_query_rec->query_context;
\r
345 p_port = __endpt_parent( p_endpt );
\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
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
359 cl_obj_unlock( &p_endpt->obj );
\r
361 if( p_query_rec->status != IB_SUCCESS )
\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
373 p_path = ib_get_query_path_rec( p_query_rec->p_result_mad, 0 );
\r
375 cl_memclr( &av_attr, sizeof(ib_av_attr_t) );
\r
377 av_attr.port_num = p_port->port_num;
\r
379 av_attr.sl = ib_path_rec_sl( p_path );
\r
380 av_attr.dlid = p_path->dlid;
\r
382 if( p_path->dgid.unicast.prefix != IB_DEFAULT_SUBNET_PREFIX )
\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
395 else if( !p_endpt->dlid )
\r
397 /* This is a subnet local endpoint that does not have its LID set. */
\r
398 p_endpt->dlid = p_path->dlid;
\r
400 * Insert the item in the LID map so that locally routed unicast
\r
401 * traffic will resolve it properly.
\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
408 av_attr.static_rate = ib_path_rec_rate( p_path );
\r
409 av_attr.path_bits = 0;
\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
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
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
428 /* Try to send all pending sends. */
\r
429 ipoib_port_resume( p_port );
\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