[MTHCA] 1. bugfix: gid lookup use wrong port number;
[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-1].p_gid_table;\r
75     CL_ASSERT (p_gid_table);\r
76 \r
77     num_gids = p_ca_attr->p_port_attr[port_num-1].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 mthca_ah *ah;\r
144         struct ibv_ah_attr attr;\r
145         struct ibv_create_ah *p_create_av;\r
146         ib_api_status_t status = IB_SUCCESS;\r
147         int AV_created = TRUE;\r
148         size_t size = max( sizeof(struct ibv_create_ah), sizeof(struct ibv_create_ah_resp) );\r
149         mlnx_ual_pd_info_t *p_pd = (mlnx_ual_pd_info_t *)h_uvp_pd;\r
150         mlnx_ual_hobul_t *p_hobul = p_pd->p_hobul;\r
151 \r
152         UVP_ENTER(UVP_DBG_AV);\r
153 \r
154         CL_ASSERT(p_umv_buf);\r
155 \r
156         // sanity check\r
157         if (p_av_attr->port_num == 0 || p_av_attr->port_num > p_hobul->p_hca_attr->num_ports) {\r
158                 UVP_PRINT(TRACE_LEVEL_WARNING ,UVP_DBG_AV ,\r
159                         (" invalid port number specified (%d)\n",p_av_attr->port_num));\r
160                 status = IB_INVALID_PORT;\r
161                 goto end;\r
162         }\r
163 \r
164         // convert parameters \r
165         cl_memset( &attr, 0, sizeof(attr));\r
166         status = map_itom_av_attr (p_hobul->p_hca_attr, p_av_attr, &attr);\r
167         if(status != IB_SUCCESS ) \r
168                 goto end;\r
169 \r
170         // allocate Ah object\r
171         ah = cl_zalloc( sizeof *ah );\r
172         if( !ah ) {\r
173                 status = IB_INSUFFICIENT_MEMORY;\r
174                 goto end;\r
175         }\r
176 \r
177         // fill AH partly\r
178         ah->h_uvp_pd = h_uvp_pd;\r
179         cl_memcpy( &ah->av_attr, p_av_attr, sizeof(ah->av_attr) );\r
180 \r
181         // try to create AV\r
182         err = mthca_alloc_av(to_mpd(p_pd->ibv_pd), &attr, ah, NULL);\r
183         if (err == -EAGAIN) \r
184                 AV_created = FALSE;\r
185         else\r
186         if (err) {\r
187                 UVP_PRINT(TRACE_LEVEL_ERROR ,UVP_DBG_AV , ("mthca_alloc_av failed (%d)\n", err));\r
188                 status = errno_to_iberr(err);\r
189                 goto err_alloc_av;\r
190         }\r
191 \r
192         // allocate parameters\r
193         if( !p_umv_buf->p_inout_buf ) {\r
194                 p_umv_buf->p_inout_buf = cl_zalloc( size );\r
195                 if( !p_umv_buf->p_inout_buf )\r
196                 {\r
197                         status = IB_INSUFFICIENT_MEMORY;\r
198                         goto err_mem;\r
199                 }\r
200         }\r
201 \r
202         // fill the parameters\r
203         p_umv_buf->input_size = sizeof(struct ibv_create_ah);\r
204         p_umv_buf->output_size = sizeof(struct ibv_create_ah_resp);\r
205         p_umv_buf->command = TRUE;\r
206         p_create_av = (struct ibv_create_ah *)p_umv_buf->p_inout_buf;\r
207         p_create_av->user_handle = (uint64_t)(ULONG_PTR)ah;\r
208         if (!AV_created) {\r
209                 struct mthca_ah_page *page = ah->page;\r
210                 p_create_av->mr.start = (uint64_t)(ULONG_PTR)page->buf;\r
211                 p_create_av->mr.length = g_page_size;\r
212                 p_create_av->mr.hca_va = (uint64_t)(ULONG_PTR)page->buf;\r
213                 p_create_av->mr.pd_handle        = p_pd->ibv_pd->handle;\r
214                 p_create_av->mr.pdn = to_mpd(p_pd->ibv_pd)->pdn;\r
215                 p_create_av->mr.access_flags = 0;       //local read\r
216                 p_create_av->use_mr = TRUE;\r
217                 status = IB_SUCCESS;\r
218         }\r
219         else\r
220                 status = IB_VERBS_PROCESSING_DONE;\r
221 \r
222         goto end;\r
223 \r
224 err_mem:        \r
225         mthca_free_av(ah);\r
226 err_alloc_av:   \r
227         cl_free(ah);\r
228 end:\r
229         UVP_EXIT(UVP_DBG_AV);\r
230         return status;\r
231 }\r
232 \r
233 \r
234 void\r
235 mlnx_post_create_av (\r
236     IN          const ib_pd_handle_t            h_uvp_pd,\r
237     IN          ib_api_status_t                 ioctl_status,\r
238     OUT         ib_av_handle_t                  *ph_uvp_av,\r
239     IN OUT      ci_umv_buf_t                    *p_umv_buf)\r
240 {\r
241         int err;\r
242         struct mthca_ah *ah;\r
243         struct mthca_ah_page *page;\r
244         struct ibv_create_ah_resp *p_resp;\r
245         ib_api_status_t status = IB_SUCCESS;\r
246         mlnx_ual_pd_info_t *p_pd = (mlnx_ual_pd_info_t *)h_uvp_pd;\r
247 \r
248         UVP_ENTER(UVP_DBG_AV);\r
249 \r
250         CL_ASSERT(p_umv_buf);\r
251 \r
252         p_resp = (struct ibv_create_ah_resp *)p_umv_buf->p_inout_buf;\r
253         ah = (struct mthca_ah *)(ULONG_PTR)p_resp->user_handle;\r
254 \r
255         if (IB_SUCCESS == ioctl_status) {\r
256 \r
257                 if (!mthca_is_memfree(p_pd->ibv_pd->context)) {\r
258                         page = ah->page;\r
259                         if (p_resp->use_mr) {\r
260                                 // fill mr parameters\r
261                                 page->mr.handle = p_resp->mr.mr_handle;\r
262                                 page->mr.lkey = p_resp->mr.lkey;\r
263                                 page->mr.rkey = p_resp->mr.rkey;\r
264                                 page->mr.pd = p_pd->ibv_pd;\r
265                                 page->mr.context = p_pd->ibv_pd->context;\r
266                         }\r
267                         ah->key  = page->mr.lkey;\r
268                 }\r
269                 *ph_uvp_av = (ib_av_handle_t)ah;\r
270         }\r
271         goto end;\r
272         \r
273 end:    \r
274         if (p_resp)\r
275                 cl_free( p_resp );\r
276         UVP_EXIT(UVP_DBG_AV);\r
277 }\r
278 \r
279 ib_api_status_t\r
280 mlnx_pre_query_av (\r
281         IN      const   ib_av_handle_t          h_uvp_av,\r
282         IN OUT          ci_umv_buf_t            *p_umv_buf )\r
283 {\r
284         UNREFERENCED_PARAMETER(h_uvp_av);\r
285         UNREFERENCED_PARAMETER(p_umv_buf);\r
286     UVP_ENTER(UVP_DBG_AV);\r
287     UVP_EXIT(UVP_DBG_AV);\r
288     return IB_VERBS_PROCESSING_DONE;\r
289 }\r
290 \r
291 \r
292 void\r
293 mlnx_post_query_av (\r
294         IN              const   ib_av_handle_t                          h_uvp_av,\r
295         IN                              ib_api_status_t                         ioctl_status,\r
296         IN      OUT                     ib_av_attr_t                            *p_addr_vector,\r
297         IN      OUT                     ib_pd_handle_t                          *ph_pd,\r
298         IN      OUT                     ci_umv_buf_t                            *p_umv_buf)\r
299 {\r
300         struct mthca_ah *ah = (struct mthca_ah *)h_uvp_av;\r
301         UNREFERENCED_PARAMETER(p_umv_buf);\r
302 \r
303     UVP_ENTER(UVP_DBG_AV);\r
304     CL_ASSERT(p_umv_buf);\r
305     CL_ASSERT(p_addr_vector);\r
306 \r
307     if (ioctl_status == IB_SUCCESS)\r
308     {\r
309         cl_memcpy (p_addr_vector, &ah->av_attr, sizeof (ib_av_attr_t));\r
310                 if (ph_pd)\r
311                         *ph_pd = (ib_pd_handle_t)ah->h_uvp_pd;\r
312     }\r
313     \r
314     UVP_EXIT(UVP_DBG_AV);\r
315 }\r
316 \r
317 void mthca_set_av_params( struct mthca_ah *ah_p, struct ibv_ah_attr *ah_attr );\r
318 \r
319 ib_api_status_t\r
320 mlnx_pre_modify_av (\r
321     IN          const ib_av_handle_t            h_uvp_av,\r
322     IN          const ib_av_attr_t              *p_addr_vector,\r
323     IN OUT      ci_umv_buf_t                    *p_umv_buf)\r
324 {\r
325         ib_api_status_t status ;\r
326         struct mthca_ah *mthca_ah = (struct mthca_ah *)h_uvp_av;\r
327         mlnx_ual_pd_info_t *p_pd_info;\r
328         mlnx_ual_hobul_t *p_hobul;\r
329         struct ibv_ah_attr attr;\r
330 \r
331         UNREFERENCED_PARAMETER(p_umv_buf);\r
332         \r
333         UVP_ENTER(UVP_DBG_AV);\r
334         \r
335         CL_ASSERT(p_umv_buf);\r
336                 \r
337         p_pd_info = mthca_ah->h_uvp_pd;\r
338         CL_ASSERT (p_pd_info);\r
339 \r
340         p_hobul = p_pd_info->p_hobul;\r
341         CL_ASSERT (p_hobul);\r
342 \r
343         status = map_itom_av_attr (p_hobul->p_hca_attr, p_addr_vector, &attr);\r
344         if(status != IB_SUCCESS)        return status;\r
345         \r
346         mthca_set_av_params( mthca_ah, &attr);\r
347         cl_memcpy (&mthca_ah->av_attr, p_addr_vector, sizeof(ib_av_attr_t));\r
348         \r
349         UVP_EXIT(UVP_DBG_AV);\r
350 \r
351         return IB_VERBS_PROCESSING_DONE;\r
352 }\r
353 \r
354 void\r
355 mlnx_post_modify_av (\r
356     IN          const ib_av_handle_t    h_uvp_av,\r
357     IN          ib_api_status_t         ioctl_status,\r
358     IN OUT      ci_umv_buf_t            *p_umv_buf)\r
359 {\r
360     UVP_ENTER(UVP_DBG_AV);\r
361     UVP_EXIT(UVP_DBG_AV);\r
362     return;\r
363 }\r
364 \r
365 \r
366 ib_api_status_t\r
367 mlnx_pre_destroy_av (\r
368     IN          const ib_av_handle_t            h_uvp_av)\r
369 {\r
370         UVP_ENTER(UVP_DBG_AV);\r
371         UVP_EXIT(UVP_DBG_AV);\r
372         return IB_SUCCESS;\r
373 }\r
374 \r
375 void\r
376 mlnx_post_destroy_av (\r
377     IN          const ib_av_handle_t            h_uvp_av,\r
378     IN          ib_api_status_t                 ioctl_status)\r
379 {\r
380         struct mthca_ah *mthca_ah = (struct mthca_ah *)h_uvp_av;\r
381         UNREFERENCED_PARAMETER(ioctl_status);\r
382 \r
383         UVP_ENTER(UVP_DBG_AV);\r
384         CL_ASSERT (h_uvp_av);\r
385         mthca_free_av(mthca_ah);\r
386         cl_free(mthca_ah);\r
387         UVP_EXIT(UVP_DBG_AV);\r
388         return;\r
389 }\r
390 \r