[IBAL] handle the IOC_REMOVE event
[mirror/winof/.git] / core / al / al_query.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. \r
4  *\r
5  * This software is available to you under the OpenIB.org BSD license\r
6  * below:\r
7  *\r
8  *     Redistribution and use in source and binary forms, with or\r
9  *     without modification, are permitted provided that the following\r
10  *     conditions are met:\r
11  *\r
12  *      - Redistributions of source code must retain the above\r
13  *        copyright notice, this list of conditions and the following\r
14  *        disclaimer.\r
15  *\r
16  *      - Redistributions in binary form must reproduce the above\r
17  *        copyright notice, this list of conditions and the following\r
18  *        disclaimer in the documentation and/or other materials\r
19  *        provided with the distribution.\r
20  *\r
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
24  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
25  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
26  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
27  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
28  * SOFTWARE.\r
29  *\r
30  * $Id$\r
31  */\r
32 \r
33 #include <iba/ib_al.h>\r
34 #include <complib/cl_timer.h>\r
35 \r
36 #include "al.h"\r
37 #include "al_ca.h"\r
38 #include "al_common.h"\r
39 #include "al_debug.h"\r
40 \r
41 #if defined(EVENT_TRACING)\r
42 #ifdef offsetof\r
43 #undef offsetof\r
44 #endif\r
45 #include "al_query.tmh"\r
46 #endif\r
47 #include "al_mgr.h"\r
48 #include "al_query.h"\r
49 #include "ib_common.h"\r
50 \r
51 \r
52 #define PR102982\r
53 \r
54 \r
55 static ib_api_status_t\r
56 query_sa(\r
57         IN                              al_query_t                                      *p_query,\r
58         IN              const   ib_query_req_t* const           p_query_req,\r
59         IN              const   ib_al_flags_t                           flags );\r
60 \r
61 void\r
62 query_req_cb(\r
63         IN                              al_sa_req_t                                     *p_sa_req,\r
64         IN                              ib_mad_element_t                        *p_mad_response );\r
65 \r
66 \r
67 ib_api_status_t\r
68 ib_query(\r
69         IN              const   ib_al_handle_t                          h_al,\r
70         IN              const   ib_query_req_t* const           p_query_req,\r
71                 OUT                     ib_query_handle_t* const        ph_query OPTIONAL )\r
72 {\r
73         al_query_t                              *p_query;\r
74         ib_api_status_t                 status;\r
75 \r
76         AL_ENTER( AL_DBG_QUERY );\r
77 \r
78         if( AL_OBJ_INVALID_HANDLE( h_al, AL_OBJ_TYPE_H_AL ) )\r
79         {\r
80                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_AL_HANDLE\n") );\r
81                 return IB_INVALID_AL_HANDLE;\r
82         }\r
83         if( !p_query_req )\r
84         {\r
85                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PARAMETER\n") );\r
86                 return IB_INVALID_PARAMETER;\r
87         }\r
88         if( (p_query_req->flags & IB_FLAGS_SYNC) && !cl_is_blockable() )\r
89         {\r
90                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_UNSUPPORTED\n") );\r
91                 return IB_UNSUPPORTED;\r
92         }\r
93 \r
94         /* Allocate a new query. */\r
95         p_query = cl_zalloc( sizeof( al_query_t ) );\r
96         if( !p_query )\r
97         {\r
98                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("insufficient memory\n") );\r
99                 return IB_INSUFFICIENT_MEMORY;\r
100         }\r
101 \r
102         /* Copy the query context information. */\r
103         p_query->sa_req.pfn_sa_req_cb = query_req_cb;\r
104         p_query->sa_req.user_context = p_query_req->query_context;\r
105         p_query->pfn_query_cb = p_query_req->pfn_query_cb;\r
106         p_query->query_type = p_query_req->query_type;\r
107 \r
108         /* Track the query with the AL instance. */\r
109         al_insert_query( h_al, p_query );\r
110 \r
111         /* Issue the MAD to the SA. */\r
112         status = query_sa( p_query, p_query_req, p_query_req->flags );\r
113         if( status != IB_SUCCESS && status != IB_INVALID_GUID )\r
114         {\r
115                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
116                         ("query_sa failed: %s\n", ib_get_err_str(status) ) );\r
117         }\r
118 \r
119         /* Cleanup from issuing the query if it failed or was synchronous. */\r
120         if( status != IB_SUCCESS )\r
121         {\r
122                 al_remove_query( p_query );\r
123                 cl_free( p_query );\r
124         }\r
125         else if( ph_query )\r
126         {\r
127                 *ph_query = p_query;\r
128         }\r
129 \r
130         AL_EXIT( AL_DBG_QUERY );\r
131         return status;\r
132 }\r
133 \r
134 \r
135 \r
136 /*\r
137  * Query the SA based on the user's request.\r
138  */\r
139 static ib_api_status_t\r
140 query_sa(\r
141         IN                              al_query_t                                      *p_query,\r
142         IN              const   ib_query_req_t* const           p_query_req,\r
143         IN              const   ib_al_flags_t                           flags )\r
144 {\r
145         ib_user_query_t                         sa_req, *p_sa_req;\r
146         union _query_sa_recs\r
147         {\r
148                 ib_service_record_t             svc;\r
149                 ib_node_record_t                node;\r
150                 ib_portinfo_record_t    portinfo;\r
151                 ib_path_rec_t                   path;\r
152                 ib_class_port_info_t    class_port_info;\r
153         }       rec;\r
154         ib_api_status_t                 status;\r
155 \r
156         AL_ENTER( AL_DBG_QUERY );\r
157 \r
158         cl_memclr( &rec, sizeof(rec) );\r
159 \r
160         /* Set the request information. */\r
161         p_sa_req = &sa_req;\r
162         sa_req.method = IB_MAD_METHOD_GETTABLE;\r
163 \r
164         /* Set the MAD attributes and component mask correctly. */\r
165         switch( p_query_req->query_type )\r
166         {\r
167         case IB_QUERY_USER_DEFINED:\r
168                 AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_QUERY, ("USER_DEFINED\n") );\r
169                 p_sa_req = (ib_user_query_t* __ptr64)p_query_req->p_query_input;\r
170                 if( !p_sa_req->method )\r
171                 {\r
172                         AL_EXIT( AL_DBG_QUERY );\r
173                         return IB_INVALID_SETTING;\r
174                 }\r
175                 break;\r
176 \r
177         case IB_QUERY_ALL_SVC_RECS:\r
178                 AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_QUERY, ("IB_QUERY_ALL_SVC_RECS\n") );\r
179                 sa_req.attr_id = IB_MAD_ATTR_SERVICE_RECORD;\r
180                 sa_req.attr_size = sizeof( ib_service_record_t );\r
181                 sa_req.comp_mask = 0;\r
182                 sa_req.p_attr = &rec.svc;\r
183                 break;\r
184 \r
185         case IB_QUERY_SVC_REC_BY_NAME:\r
186                 AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_QUERY, ("SVC_REC_BY_NAME\n") );\r
187                 sa_req.attr_id = IB_MAD_ATTR_SERVICE_RECORD;\r
188                 sa_req.attr_size = sizeof( ib_service_record_t );\r
189                 sa_req.comp_mask = IB_SR_COMPMASK_SNAME;\r
190                 sa_req.p_attr = &rec.svc;\r
191                 cl_memcpy( rec.svc.service_name, p_query_req->p_query_input,\r
192                         sizeof( ib_svc_name_t ) );\r
193                 break;\r
194 \r
195         case IB_QUERY_SVC_REC_BY_ID:\r
196                 AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_QUERY, ("SVC_REC_BY_ID\n") );\r
197                 sa_req.attr_id = IB_MAD_ATTR_SERVICE_RECORD;\r
198                 sa_req.attr_size = sizeof( ib_service_record_t );\r
199                 sa_req.comp_mask = IB_SR_COMPMASK_SID;\r
200                 sa_req.p_attr = &rec.svc;\r
201                 rec.svc.service_id = *(ib_net64_t* __ptr64)(p_query_req->p_query_input);\r
202                 break;\r
203 \r
204         case IB_QUERY_CLASS_PORT_INFO:\r
205                 AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_QUERY, ("IB_QUERY_CLASS_PORT_INFO\n") );\r
206                 sa_req.method = IB_MAD_METHOD_GET;\r
207                 sa_req.attr_id = IB_MAD_ATTR_CLASS_PORT_INFO;\r
208                 sa_req.attr_size = sizeof( ib_class_port_info_t );\r
209                 sa_req.comp_mask = 0;\r
210                 sa_req.p_attr = &rec.class_port_info;\r
211                 break;\r
212 \r
213         case IB_QUERY_NODE_REC_BY_NODE_GUID:\r
214                 AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_QUERY, ("NODE_REC_BY_NODE_GUID\n") );\r
215                 /*\r
216                  *      15.2.5.2:\r
217                  * if >1 ports on of a CA/RTR the subnet return multiple\r
218                  * record\r
219                  */\r
220                 sa_req.attr_id = IB_MAD_ATTR_NODE_RECORD;\r
221                 sa_req.attr_size = sizeof( ib_node_record_t );\r
222                 sa_req.comp_mask = IB_NR_COMPMASK_NODEGUID;\r
223                 sa_req.p_attr = &rec.node;\r
224                 rec.node.node_info.node_guid =\r
225                         *(ib_net64_t* __ptr64)(p_query_req->p_query_input);\r
226                 break;\r
227 \r
228         case IB_QUERY_PORT_REC_BY_LID:\r
229                 AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_QUERY, ("PORT_REC_BY_LID\n") );\r
230                 sa_req.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;\r
231                 sa_req.attr_size = sizeof( ib_portinfo_record_t );\r
232                 sa_req.comp_mask = IB_PIR_COMPMASK_BASELID;\r
233                 sa_req.p_attr = &rec.portinfo;\r
234                 rec.portinfo.port_info.base_lid =\r
235                         *(ib_net16_t* __ptr64)(p_query_req->p_query_input);\r
236                 break;\r
237 \r
238         case IB_QUERY_PATH_REC_BY_PORT_GUIDS:\r
239                 AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_QUERY, ("PATH_REC_BY_PORT_GUIDS\n") );\r
240                 sa_req.attr_id = IB_MAD_ATTR_PATH_RECORD;\r
241                 sa_req.attr_size = sizeof( ib_path_rec_t );\r
242                 sa_req.comp_mask = (IB_PR_COMPMASK_DGID |\r
243                         IB_PR_COMPMASK_SGID | IB_PR_COMPMASK_NUM_PATH);\r
244                 sa_req.p_attr = &rec.path;\r
245                 ib_gid_set_default( &rec.path.dgid, ((ib_guid_pair_t* __ptr64)\r
246                         (p_query_req->p_query_input))->dest_guid );\r
247                 ib_gid_set_default( &rec.path.sgid, ((ib_guid_pair_t* __ptr64)\r
248                         (p_query_req->p_query_input))->src_guid );\r
249                 rec.path.num_path = 1;\r
250                 break;\r
251 \r
252         case IB_QUERY_PATH_REC_BY_GIDS:\r
253                 AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_QUERY, ("PATH_REC_BY_GIDS\n") );\r
254                 sa_req.attr_id = IB_MAD_ATTR_PATH_RECORD;\r
255                 sa_req.attr_size = sizeof( ib_path_rec_t );\r
256                 sa_req.comp_mask = (IB_PR_COMPMASK_DGID |\r
257                         IB_PR_COMPMASK_SGID | IB_PR_COMPMASK_NUM_PATH);\r
258                 sa_req.p_attr = &rec.path;\r
259                 cl_memcpy( &rec.path.dgid, &((ib_gid_pair_t* __ptr64)\r
260                         (p_query_req->p_query_input))->dest_gid, sizeof( ib_gid_t ) );\r
261                 cl_memcpy( &rec.path.sgid, &((ib_gid_pair_t* __ptr64)\r
262                         (p_query_req->p_query_input))->src_gid, sizeof( ib_gid_t ) );\r
263                 rec.path.num_path = 1;\r
264                 break;\r
265 \r
266         case IB_QUERY_PATH_REC_BY_LIDS:\r
267                 AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_QUERY, ("PATH_REC_BY_LIDS\n") );\r
268                 /* SGID must be provided for GET_TABLE requests. */\r
269                 sa_req.method = IB_MAD_METHOD_GET;\r
270                 sa_req.attr_id = IB_MAD_ATTR_PATH_RECORD;\r
271                 sa_req.attr_size = sizeof( ib_path_rec_t );\r
272                 sa_req.comp_mask =\r
273                         (IB_PR_COMPMASK_DLID | IB_PR_COMPMASK_SLID);\r
274                 sa_req.p_attr = &rec.path;\r
275                 rec.path.dlid = \r
276                         ((ib_lid_pair_t* __ptr64)(p_query_req->p_query_input))->dest_lid;\r
277                 rec.path.slid =\r
278                         ((ib_lid_pair_t* __ptr64)(p_query_req->p_query_input))->src_lid;\r
279 #ifdef PR102982\r
280                 rec.path.num_path = 1;\r
281 #endif\r
282                 break;\r
283 \r
284         default:\r
285                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("UNKNOWN\n") );\r
286                 CL_ASSERT( p_query_req->query_type == IB_QUERY_USER_DEFINED ||\r
287                         p_query_req->query_type == IB_QUERY_ALL_SVC_RECS ||\r
288                         p_query_req->query_type == IB_QUERY_SVC_REC_BY_NAME ||\r
289                         p_query_req->query_type == IB_QUERY_SVC_REC_BY_ID ||\r
290                         p_query_req->query_type == IB_QUERY_CLASS_PORT_INFO ||\r
291                         p_query_req->query_type == IB_QUERY_NODE_REC_BY_NODE_GUID ||\r
292                         p_query_req->query_type == IB_QUERY_PORT_REC_BY_LID ||\r
293                         p_query_req->query_type == IB_QUERY_PATH_REC_BY_PORT_GUIDS ||\r
294                         p_query_req->query_type == IB_QUERY_PATH_REC_BY_GIDS ||\r
295                         p_query_req->query_type == IB_QUERY_PATH_REC_BY_LIDS );\r
296 \r
297                 return IB_ERROR;\r
298         }\r
299 \r
300         status = al_send_sa_req(\r
301                 &p_query->sa_req, p_query_req->port_guid, p_query_req->timeout_ms,\r
302                 p_query_req->retry_cnt, p_sa_req, flags );\r
303         AL_EXIT( AL_DBG_QUERY );\r
304         return status;\r
305 }\r
306 \r
307 \r
308 \r
309 /*\r
310  * Query request completion callback.\r
311  */\r
312 void\r
313 query_req_cb(\r
314         IN                              al_sa_req_t                                     *p_sa_req,\r
315         IN                              ib_mad_element_t                        *p_mad_response )\r
316 {\r
317         al_query_t                      *p_query;\r
318         ib_query_rec_t          query_rec;\r
319         ib_sa_mad_t                     *p_sa_mad;\r
320 \r
321         AL_ENTER( AL_DBG_QUERY );\r
322         p_query = PARENT_STRUCT( p_sa_req, al_query_t, sa_req );\r
323 \r
324         /* Initialize the results of the query. */\r
325         cl_memclr( &query_rec, sizeof( ib_query_rec_t ) );\r
326         query_rec.status = p_sa_req->status;\r
327         query_rec.query_context = p_query->sa_req.user_context;\r
328         query_rec.query_type = p_query->query_type;\r
329 \r
330         /* Form the result of the query, if we got one. */\r
331         if( query_rec.status == IB_SUCCESS )\r
332         {\r
333                 AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_QUERY,\r
334                         ("query succeeded\n") );\r
335 \r
336                 CL_ASSERT( p_mad_response );\r
337                 p_sa_mad = (ib_sa_mad_t*)p_mad_response->p_mad_buf;\r
338 \r
339                 if (ib_get_attr_size( p_sa_mad->attr_offset ) != 0)\r
340                 {\r
341                         query_rec.result_cnt =\r
342                                 ( ( p_mad_response->size - IB_SA_MAD_HDR_SIZE ) /\r
343                                 ib_get_attr_size( p_sa_mad->attr_offset ) );\r
344                 }\r
345                 else\r
346                 {\r
347                         query_rec.result_cnt = 0;\r
348                 }\r
349 \r
350                 query_rec.p_result_mad = p_mad_response;\r
351         }\r
352         else\r
353         {\r
354                 AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_QUERY,\r
355                         ("query failed: %s\n", ib_get_err_str(query_rec.status) ) );\r
356                 if( p_mad_response )\r
357                         query_rec.p_result_mad = p_mad_response;\r
358         }\r
359 \r
360         /*\r
361          * Handing an internal MAD to a client.\r
362          * Track the MAD element with the client's AL instance.\r
363          */\r
364         if( p_mad_response )\r
365                 al_handoff_mad( p_query->h_al, p_mad_response );\r
366 \r
367         /* Notify the user of the result. */\r
368         p_query->pfn_query_cb( &query_rec );\r
369 \r
370         /* Cleanup from issuing the query. */\r
371         al_remove_query( p_query );\r
372         cl_free( p_query );\r
373 \r
374         AL_EXIT( AL_DBG_QUERY );\r
375 }\r