71ebbe3f927ef259791805d884aee5b270655c85
[mirror/winof/.git] / hw / mthca / user / mlnx_ual_av.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  * Copyright (c) 2004-2005 Mellanox Technologies, Inc. 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: mlnx_ual_av.c 256 2005-08-07 13:23:31Z sleybo $\r
31  */\r
32 \r
33 #include "mt_l2w.h"\r
34 #include "mlnx_uvp.h"\r
35 #include "mx_abi.h"\r
36 \r
37 #include "mlnx_ual_main.h"\r
38 #if defined(EVENT_TRACING)\r
39 #include "mlnx_ual_av.tmh"\r
40 #endif\r
41 \r
42 void\r
43 mlnx_get_av_interface (\r
44     IN OUT      uvp_interface_t         *p_uvp )\r
45 {\r
46 \r
47     CL_ASSERT(p_uvp);\r
48 \r
49     /*\r
50      * Address Vector Management Verbs\r
51      */\r
52     p_uvp->pre_create_av  = mlnx_pre_create_av;\r
53     p_uvp->post_create_av = mlnx_post_create_av;\r
54     p_uvp->pre_query_av   = mlnx_pre_query_av;\r
55     p_uvp->post_query_av  = mlnx_post_query_av;\r
56     p_uvp->pre_modify_av   = mlnx_pre_modify_av;\r
57     p_uvp->post_modify_av  = mlnx_post_modify_av;\r
58     p_uvp->pre_destroy_av  = mlnx_pre_destroy_av;\r
59     p_uvp->post_destroy_av = mlnx_post_destroy_av;\r
60 \r
61 }\r
62 \r
63 \r
64 uint8_t\r
65 gid_to_index_lookup (\r
66     IN          ib_ca_attr_t    *p_ca_attr,\r
67     IN          uint8_t         port_num,\r
68     IN          uint8_t         *raw_gid)\r
69 {\r
70     ib_gid_t *p_gid_table = NULL;\r
71     uint8_t i, index = 0;\r
72     uint16_t num_gids;\r
73 \r
74     p_gid_table = p_ca_attr->p_port_attr[port_num].p_gid_table;\r
75     CL_ASSERT (p_gid_table);\r
76 \r
77     num_gids = p_ca_attr->p_port_attr[port_num].num_gids;\r
78     UVP_PRINT(TRACE_LEVEL_INFORMATION, UVP_DBG_AV, \r
79               ("Port %d has %d gids\n", port_num, num_gids));\r
80 \r
81     for (i = 0; i < num_gids; i++)\r
82     {\r
83         if (cl_memcmp (raw_gid, p_gid_table[i].raw, sizeof (ib_gid_t)))\r
84         {\r
85             UVP_PRINT(TRACE_LEVEL_INFORMATION ,UVP_DBG_AV ,\r
86                       ("found GID at index %d\n", i));\r
87             index = i;\r
88             break;\r
89         }\r
90     }\r
91     return index;\r
92 }\r
93 \r
94 ib_api_status_t\r
95 map_itom_av_attr (\r
96     IN          ib_ca_attr_t            *p_ca_attr,\r
97     IN          const ib_av_attr_t      *p_av_attr,\r
98     OUT         struct ibv_ah_attr              *p_attr)\r
99 {\r
100 \r
101 \r
102         ib_api_status_t status = IB_SUCCESS;\r
103         if (p_av_attr->port_num == 0 || \r
104                 p_av_attr->port_num > p_ca_attr->num_ports) {\r
105                 UVP_PRINT(TRACE_LEVEL_WARNING ,UVP_DBG_AV ,\r
106                         (" invalid port number specified (%d)\n",p_av_attr->port_num));\r
107                 return IB_INVALID_PORT;\r
108         }\r
109 \r
110         p_attr->sl = p_av_attr->sl;\r
111         p_attr->port_num = p_av_attr->port_num;\r
112         p_attr->dlid = CL_NTOH16 (p_av_attr->dlid);\r
113         p_attr->src_path_bits = p_av_attr->path_bits; // PATH:\r
114 \r
115         //TODO: how static_rate is coded ?\r
116         p_attr->static_rate   =\r
117                 (p_av_attr->static_rate == IB_PATH_RECORD_RATE_10_GBS ? 0 : 3);\r
118                 \r
119         /* For global destination or Multicast address:*/\r
120         if (p_av_attr->grh_valid) {\r
121                 p_attr->is_global = TRUE;\r
122                 p_attr->grh.hop_limit            = p_av_attr->grh.hop_limit;\r
123                 ib_grh_get_ver_class_flow( p_av_attr->grh.ver_class_flow, NULL,\r
124                         &p_attr->grh.traffic_class, &p_attr->grh.flow_label );\r
125                 p_attr->grh.sgid_index = gid_to_index_lookup (p_ca_attr, \r
126                         p_av_attr->port_num, (uint8_t *) p_av_attr->grh.src_gid.raw); \r
127                 cl_memcpy (p_attr->grh.dgid.raw, p_av_attr->grh.dest_gid.raw, \r
128                         sizeof (IB_gid_t));\r
129         }else{\r
130                 p_attr->is_global = FALSE;\r
131         }\r
132 \r
133         return status;\r
134\r
135 \r
136 ib_api_status_t\r
137 mlnx_pre_create_av (\r
138     IN          const ib_pd_handle_t            h_uvp_pd,\r
139     IN          const ib_av_attr_t              *p_av_attr,\r
140     IN OUT      ci_umv_buf_t                    *p_umv_buf)\r
141 {\r
142         int err;\r
143         struct ibv_create_ah *p_create_av;\r
144         ib_api_status_t status = IB_SUCCESS;\r
145         size_t size = max( sizeof(struct ibv_create_ah), sizeof(struct ibv_create_ah_resp) );\r
146         mlnx_ual_pd_info_t *p_pd = (mlnx_ual_pd_info_t *)h_uvp_pd;\r
147         mlnx_ual_hobul_t *p_hobul = p_pd->p_hobul;\r
148 \r
149         UVP_ENTER(UVP_DBG_AV);\r
150 \r
151         CL_ASSERT(p_umv_buf);\r
152 \r
153         if( !p_umv_buf->p_inout_buf )\r
154         {\r
155                 p_umv_buf->p_inout_buf = cl_zalloc( size );\r
156                 if( !p_umv_buf->p_inout_buf )\r
157                 {\r
158                         status = IB_INSUFFICIENT_MEMORY;\r
159                         goto err_memory;\r
160                 }\r
161         }\r
162 \r
163         if (p_av_attr->port_num == 0 || p_av_attr->port_num > p_hobul->p_hca_attr->num_ports) {\r
164                 UVP_PRINT(TRACE_LEVEL_WARNING ,UVP_DBG_AV ,\r
165                         (" invalid port number specified (%d)\n",p_av_attr->port_num));\r
166                 return IB_INVALID_PORT;\r
167         }\r
168 \r
169         p_umv_buf->input_size = sizeof(struct ibv_create_ah);\r
170         p_umv_buf->output_size = sizeof(struct ibv_create_ah_resp);\r
171         p_umv_buf->command = TRUE;\r
172 \r
173         /* allocate ibv_ah */\r
174         p_create_av = (struct ibv_create_ah *)p_umv_buf->p_inout_buf;\r
175         err = p_hobul->ibv_ctx->ops.create_ah_pre(p_pd->ibv_pd, p_create_av);\r
176         if (err) {\r
177                 UVP_PRINT(TRACE_LEVEL_ERROR ,UVP_DBG_AV , ("mthca_alloc_av_pre failed (%d)\n", err));\r
178                 status = errno_to_iberr(err);\r
179                 goto err_alloc_av;\r
180         }\r
181 \r
182         goto end;\r
183                 \r
184 err_alloc_av:\r
185         cl_free(p_umv_buf->p_inout_buf);\r
186 err_memory:\r
187 end:\r
188                 UVP_EXIT(UVP_DBG_AV);\r
189                 return status;\r
190 }\r
191 \r
192 \r
193 void\r
194 mlnx_post_create_av (\r
195     IN          const ib_pd_handle_t            h_uvp_pd,\r
196     IN          ib_api_status_t                 ioctl_status,\r
197     OUT         ib_av_handle_t                  *ph_uvp_av,\r
198     IN OUT      ci_umv_buf_t                    *p_umv_buf)\r
199 {\r
200         int err;\r
201         struct ibv_ah_attr attr;\r
202         struct ibv_ah *ibv_ah;\r
203         struct ibv_create_ah_resp *p_resp;\r
204         mlnx_ual_av_info_t *av_info;\r
205         ib_api_status_t status = IB_SUCCESS;\r
206         mlnx_ual_pd_info_t *p_pd = (mlnx_ual_pd_info_t *)h_uvp_pd;\r
207         mlnx_ual_hobul_t *p_hobul = p_pd->p_hobul;\r
208 \r
209         UVP_ENTER(UVP_DBG_AV);\r
210 \r
211         CL_ASSERT(p_hobul);\r
212         CL_ASSERT(p_umv_buf);\r
213 \r
214         p_resp = (struct ibv_create_ah_resp *)p_umv_buf->p_inout_buf;\r
215 \r
216         if (IB_SUCCESS == ioctl_status) {\r
217 \r
218                 /* convert parameters */\r
219                 cl_memset( &attr, 0, sizeof(attr));\r
220                 status = map_itom_av_attr (p_hobul->p_hca_attr, &p_resp->av_attr, &attr);\r
221                 if(status != IB_SUCCESS ) \r
222                         goto err_map_itom;\r
223                 /* allocate ibv_av */\r
224                 ibv_ah = p_hobul->ibv_ctx->ops.create_ah_post(p_pd->ibv_pd, &attr, p_resp);\r
225                 if (IS_ERR(ibv_ah)) {\r
226                         err = PTR_ERR(ibv_ah);\r
227                         UVP_PRINT(TRACE_LEVEL_ERROR ,UVP_DBG_AV , ("mthca_create_av_post failed (%d)\n", err));\r
228                         status = errno_to_iberr(err);\r
229                         goto err_create_ah;\r
230                 }\r
231 \r
232                 /* allocate av */\r
233                 av_info = (mlnx_ual_av_info_t *)cl_zalloc( sizeof(mlnx_ual_av_info_t) );\r
234                 if( !av_info ) {\r
235                         status = IB_INSUFFICIENT_MEMORY;\r
236                         goto err_alloc_av_info;\r
237                 }\r
238 \r
239                 /* return results */\r
240                 cl_memcpy( &av_info->av_attr, &p_resp->av_attr, sizeof(av_info->av_attr) );\r
241                 av_info->h_uvp_pd = p_pd;\r
242                 av_info->ibv_ah = ibv_ah;\r
243                 *ph_uvp_av = (ib_av_handle_t)av_info;\r
244 \r
245         }\r
246         goto end;\r
247         \r
248 err_alloc_av_info:      \r
249         p_hobul->ibv_ctx->ops.destroy_ah(ibv_ah);\r
250 err_map_itom:   \r
251 err_create_ah:\r
252 end:    \r
253         if (p_resp)\r
254                 cl_free( p_resp );\r
255         UVP_EXIT(UVP_DBG_AV);\r
256         return;\r
257 }\r
258 \r
259 ib_api_status_t\r
260 mlnx_pre_query_av (\r
261         IN      const   ib_av_handle_t          h_uvp_av,\r
262         IN OUT          ci_umv_buf_t            *p_umv_buf )\r
263 {\r
264         UNREFERENCED_PARAMETER(h_uvp_av);\r
265         UNREFERENCED_PARAMETER(p_umv_buf);\r
266     UVP_ENTER(UVP_DBG_AV);\r
267     UVP_EXIT(UVP_DBG_AV);\r
268     return IB_VERBS_PROCESSING_DONE;\r
269 }\r
270 \r
271 \r
272 void\r
273 mlnx_post_query_av (\r
274         IN              const   ib_av_handle_t                          h_uvp_av,\r
275         IN                              ib_api_status_t                         ioctl_status,\r
276         IN      OUT                     ib_av_attr_t                            *p_addr_vector,\r
277         IN      OUT                     ib_pd_handle_t                          *ph_pd,\r
278         IN      OUT                     ci_umv_buf_t                            *p_umv_buf)\r
279 {\r
280         mlnx_ual_av_info_t *av_info = (mlnx_ual_av_info_t *)h_uvp_av;\r
281         UNREFERENCED_PARAMETER(p_umv_buf);\r
282 \r
283     UVP_ENTER(UVP_DBG_AV);\r
284     CL_ASSERT(p_umv_buf);\r
285     CL_ASSERT(p_addr_vector);\r
286 \r
287     if (ioctl_status == IB_SUCCESS)\r
288     {\r
289         cl_memcpy (p_addr_vector, &av_info->av_attr, sizeof (ib_av_attr_t));\r
290                 if (ph_pd)\r
291                         *ph_pd = (ib_pd_handle_t)av_info->h_uvp_pd;\r
292     }\r
293     \r
294     UVP_EXIT(UVP_DBG_AV);\r
295 }\r
296 \r
297 void mthca_set_av_params(       struct mthca_ah *ah_p, struct ibv_ah_attr *ah_attr );\r
298 \r
299 ib_api_status_t\r
300 mlnx_pre_modify_av (\r
301     IN          const ib_av_handle_t            h_uvp_av,\r
302     IN          const ib_av_attr_t              *p_addr_vector,\r
303     IN OUT      ci_umv_buf_t                    *p_umv_buf)\r
304 {\r
305         ib_api_status_t status ;\r
306         struct ibv_ah *ibv_ah = (struct ibv_ah *)h_uvp_av->ibv_ah;\r
307         struct mthca_ah *mthca_ah = (struct mthca_ah *)ibv_ah;\r
308         mlnx_ual_pd_info_t *p_pd_info;\r
309         mlnx_ual_hobul_t *p_hobul;\r
310         struct ibv_ah_attr attr;\r
311         int err;\r
312 \r
313         UNREFERENCED_PARAMETER(p_umv_buf);\r
314         \r
315         UVP_ENTER(UVP_DBG_AV);\r
316         \r
317         CL_ASSERT(p_umv_buf);\r
318                 \r
319         p_pd_info = h_uvp_av->h_uvp_pd;\r
320         CL_ASSERT (p_pd_info);\r
321 \r
322         p_hobul = p_pd_info->p_hobul;\r
323         CL_ASSERT (p_hobul);\r
324 \r
325         status = map_itom_av_attr (p_hobul->p_hca_attr, p_addr_vector, &attr);\r
326         if(status != IB_SUCCESS)        return status;\r
327         \r
328         mthca_set_av_params( mthca_ah, &attr);\r
329         cl_memcpy (&h_uvp_av->av_attr, p_addr_vector, sizeof(ib_av_attr_t));\r
330         \r
331         UVP_EXIT(UVP_DBG_AV);\r
332 \r
333         return IB_VERBS_PROCESSING_DONE;\r
334 }\r
335 \r
336 void\r
337 mlnx_post_modify_av (\r
338     IN          const ib_av_handle_t    h_uvp_av,\r
339     IN          ib_api_status_t         ioctl_status,\r
340     IN OUT      ci_umv_buf_t            *p_umv_buf)\r
341 {\r
342     UVP_ENTER(UVP_DBG_AV);\r
343     UVP_EXIT(UVP_DBG_AV);\r
344     return;\r
345 }\r
346 \r
347 \r
348 ib_api_status_t\r
349 mlnx_pre_destroy_av (\r
350     IN          const ib_av_handle_t            h_uvp_av)\r
351 {\r
352         UVP_ENTER(UVP_DBG_AV);\r
353         UVP_EXIT(UVP_DBG_AV);\r
354         return IB_SUCCESS;\r
355 }\r
356 \r
357 void\r
358 mlnx_post_destroy_av (\r
359     IN          const ib_av_handle_t            h_uvp_av,\r
360     IN          ib_api_status_t                 ioctl_status)\r
361 {\r
362         UNREFERENCED_PARAMETER(ioctl_status);\r
363 \r
364     UVP_ENTER(UVP_DBG_AV);\r
365     CL_ASSERT (h_uvp_av || h_uvp_av->ibv_ah);\r
366         h_uvp_av->ibv_ah->pd->context->ops.destroy_ah(h_uvp_av->ibv_ah);\r
367     UVP_EXIT(UVP_DBG_AV);\r
368     return;\r
369 }\r
370 \r