6bb6daf376186901f6733630f3b0c623b438fc8f
[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  * Portions Copyright (c) 2008 Microsoft Corporation.  All rights reserved.\r
5  *\r
6  * This software is available to you under the OpenIB.org BSD license\r
7  * below:\r
8  *\r
9  *     Redistribution and use in source and binary forms, with or\r
10  *     without modification, are permitted provided that the following\r
11  *     conditions are met:\r
12  *\r
13  *      - Redistributions of source code must retain the above\r
14  *        copyright notice, this list of conditions and the following\r
15  *        disclaimer.\r
16  *\r
17  *      - Redistributions in binary form must reproduce the above\r
18  *        copyright notice, this list of conditions and the following\r
19  *        disclaimer in the documentation and/or other materials\r
20  *        provided with the distribution.\r
21  *\r
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
25  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
26  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
27  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
28  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
29  * SOFTWARE.\r
30  *\r
31  * $Id$\r
32  */\r
33 \r
34 #include "mt_l2w.h"\r
35 #include "mlnx_uvp.h"\r
36 #include "mx_abi.h"\r
37 \r
38 #include "mlnx_ual_main.h"\r
39 #if defined(EVENT_TRACING)\r
40 #include "mlnx_ual_av.tmh"\r
41 #endif\r
42 \r
43 \r
44 uint8_t\r
45 gid_to_index_lookup (\r
46         IN              ib_ca_attr_t    *p_ca_attr,\r
47         IN              uint8_t         port_num,\r
48         IN              uint8_t         *raw_gid)\r
49 {\r
50         ib_gid_t *p_gid_table = NULL;\r
51         uint8_t i, index = 0;\r
52         uint16_t num_gids;\r
53 \r
54         p_gid_table = p_ca_attr->p_port_attr[port_num-1].p_gid_table;\r
55         CL_ASSERT (p_gid_table);\r
56 \r
57         num_gids = p_ca_attr->p_port_attr[port_num-1].num_gids;\r
58         UVP_PRINT(TRACE_LEVEL_INFORMATION, UVP_DBG_AV, \r
59                 ("Port %d has %d gids\n", port_num, num_gids));\r
60 \r
61         for (i = 0; i < num_gids; i++)\r
62         {\r
63                 if (cl_memcmp (raw_gid, p_gid_table[i].raw, sizeof (ib_gid_t)))\r
64                 {\r
65                         UVP_PRINT(TRACE_LEVEL_INFORMATION ,UVP_DBG_AV ,\r
66                                 ("found GID at index %d\n", i));\r
67                         index = i;\r
68                         break;\r
69                 }\r
70         }\r
71         return index;\r
72 }\r
73 \r
74 ib_api_status_t\r
75 map_itom_av_attr (\r
76         IN              ib_ca_attr_t            *p_ca_attr,\r
77         IN              const ib_av_attr_t      *p_av_attr,\r
78         OUT             struct ibv_ah_attr              *p_attr)\r
79 {\r
80 \r
81 \r
82         ib_api_status_t status = IB_SUCCESS;\r
83         if (p_av_attr->port_num == 0 || \r
84                 p_av_attr->port_num > p_ca_attr->num_ports) {\r
85                 UVP_PRINT(TRACE_LEVEL_WARNING ,UVP_DBG_AV ,\r
86                         (" invalid port number specified (%d)\n",p_av_attr->port_num));\r
87                 return IB_INVALID_PORT;\r
88         }\r
89 \r
90         p_attr->sl = p_av_attr->sl;\r
91         p_attr->port_num = p_av_attr->port_num;\r
92         p_attr->dlid = CL_NTOH16 (p_av_attr->dlid);\r
93         p_attr->src_path_bits = p_av_attr->path_bits; // PATH:\r
94 \r
95         //TODO: how static_rate is coded ?\r
96         p_attr->static_rate   =\r
97                 (p_av_attr->static_rate == IB_PATH_RECORD_RATE_10_GBS ? 0 : 3);\r
98                 \r
99         /* For global destination or Multicast address:*/\r
100         if (p_av_attr->grh_valid) {\r
101                 p_attr->is_global = TRUE;\r
102                 p_attr->grh.hop_limit            = p_av_attr->grh.hop_limit;\r
103                 ib_grh_get_ver_class_flow( p_av_attr->grh.ver_class_flow, NULL,\r
104                         &p_attr->grh.traffic_class, &p_attr->grh.flow_label );\r
105                 p_attr->grh.sgid_index = gid_to_index_lookup (p_ca_attr, \r
106                         p_av_attr->port_num, (uint8_t *) p_av_attr->grh.src_gid.raw); \r
107                 cl_memcpy (p_attr->grh.dgid.raw, p_av_attr->grh.dest_gid.raw, \r
108                         sizeof (IB_gid_t));\r
109         }else{\r
110                 p_attr->is_global = FALSE;\r
111         }\r
112 \r
113         return status;\r
114\r
115 \r
116 static ib_api_status_t\r
117 __pre_create_av (\r
118         IN              const ib_pd_handle_t    h_uvp_pd,\r
119         IN              const ib_av_attr_t              *p_av_attr,\r
120         IN OUT  ci_umv_buf_t                    *p_umv_buf,\r
121            OUT  ib_av_handle_t                  *ph_uvp_av)\r
122 {\r
123         int err;\r
124         struct mthca_ah *ah;\r
125         struct ibv_ah_attr attr;\r
126         struct ibv_create_ah *p_create_av;\r
127         ib_api_status_t status = IB_SUCCESS;\r
128         size_t size = max( sizeof(struct ibv_create_ah), sizeof(struct ibv_create_ah_resp) );\r
129         mlnx_ual_pd_info_t *p_pd = (mlnx_ual_pd_info_t *)h_uvp_pd;\r
130         mlnx_ual_hobul_t *p_hobul = p_pd->p_hobul;\r
131 \r
132         UNREFERENCED_PARAMETER(ph_uvp_av);\r
133         \r
134         UVP_ENTER(UVP_DBG_AV);\r
135 \r
136         CL_ASSERT(p_umv_buf);\r
137 \r
138         // sanity check\r
139         if (p_av_attr->port_num == 0 || p_av_attr->port_num > p_hobul->p_hca_attr->num_ports) {\r
140                 UVP_PRINT(TRACE_LEVEL_WARNING ,UVP_DBG_AV ,\r
141                         (" invalid port number specified (%d)\n",p_av_attr->port_num));\r
142                 status = IB_INVALID_PORT;\r
143                 goto end;\r
144         }\r
145 \r
146         // convert parameters \r
147         cl_memset( &attr, 0, sizeof(attr));\r
148         status = map_itom_av_attr (p_hobul->p_hca_attr, p_av_attr, &attr);\r
149         if(status != IB_SUCCESS ) \r
150                 goto end;\r
151 \r
152         // allocate Ah object\r
153         ah = cl_zalloc( sizeof *ah );\r
154         if( !ah ) {\r
155                 status = IB_INSUFFICIENT_MEMORY;\r
156                 goto end;\r
157         }\r
158 \r
159         // fill AH partly\r
160         ah->h_uvp_pd = h_uvp_pd;\r
161         cl_memcpy( &ah->av_attr, p_av_attr, sizeof(ah->av_attr) );\r
162 \r
163         // try to create AV\r
164         err = mthca_alloc_av(to_mpd(p_pd->ibv_pd), &attr, ah, NULL);\r
165         if (err) {\r
166                 UVP_PRINT(TRACE_LEVEL_ERROR ,UVP_DBG_AV , ("mthca_alloc_av failed (%d)\n", err));\r
167                 status = errno_to_iberr(err);\r
168                 goto err_alloc_av;\r
169         }\r
170 \r
171         // allocate parameters\r
172         if( !p_umv_buf->p_inout_buf ) {\r
173                 p_umv_buf->p_inout_buf = cl_zalloc( size );\r
174                 if( !p_umv_buf->p_inout_buf )\r
175                 {\r
176                         status = IB_INSUFFICIENT_MEMORY;\r
177                         goto err_mem;\r
178                 }\r
179         }\r
180 \r
181         // fill the parameters\r
182         p_umv_buf->input_size = sizeof(struct ibv_create_ah);\r
183         p_umv_buf->output_size = sizeof(struct ibv_create_ah_resp);\r
184         p_umv_buf->command = TRUE;\r
185         p_create_av = (struct ibv_create_ah *)p_umv_buf->p_inout_buf;\r
186         p_create_av->user_handle = (uint64_t)(ULONG_PTR)ah;\r
187         if (ah->in_kernel) {\r
188                 struct mthca_ah_page *page = ah->page;\r
189                 p_create_av->mr.start = (uint64_t)(ULONG_PTR)page->buf;\r
190                 p_create_av->mr.length = g_page_size;\r
191                 p_create_av->mr.hca_va = (uint64_t)(ULONG_PTR)page->buf;\r
192                 p_create_av->mr.pd_handle        = p_pd->ibv_pd->handle;\r
193                 p_create_av->mr.pdn = to_mpd(p_pd->ibv_pd)->pdn;\r
194                 p_create_av->mr.access_flags = 0;       //local read\r
195                 status = IB_SUCCESS;\r
196         }\r
197         else\r
198                 status = IB_VERBS_PROCESSING_DONE;\r
199 \r
200         goto end;\r
201 \r
202 err_mem:        \r
203         mthca_free_av(ah);\r
204 err_alloc_av:   \r
205         cl_free(ah);\r
206 end:\r
207         UVP_EXIT(UVP_DBG_AV);\r
208         return status;\r
209 }\r
210 \r
211 \r
212 static void\r
213 __post_create_av (\r
214         IN              const ib_pd_handle_t    h_uvp_pd,\r
215         IN              ib_api_status_t                 ioctl_status,\r
216         IN OUT          ib_av_handle_t          *ph_uvp_av,\r
217         IN OUT  ci_umv_buf_t                    *p_umv_buf)\r
218 {\r
219         int err;\r
220         struct mthca_ah *ah;\r
221         struct mthca_ah_page *page;\r
222         struct ibv_create_ah_resp *p_resp;\r
223         ib_api_status_t status = IB_SUCCESS;\r
224         mlnx_ual_pd_info_t *p_pd = (mlnx_ual_pd_info_t *)h_uvp_pd;\r
225 \r
226         UVP_ENTER(UVP_DBG_AV);\r
227 \r
228         CL_ASSERT(p_umv_buf);\r
229 \r
230         p_resp = (struct ibv_create_ah_resp *)p_umv_buf->p_inout_buf;\r
231         ah = (struct mthca_ah *)(ULONG_PTR)p_resp->user_handle;\r
232 \r
233         if (IB_SUCCESS == ioctl_status) {\r
234 \r
235                 if (!mthca_is_memfree(p_pd->ibv_pd->context)) {\r
236                         page = ah->page;\r
237                         if (ah->in_kernel) {\r
238                                 // fill mr parameters\r
239                                 page->mr.handle = p_resp->mr.mr_handle;\r
240                                 page->mr.lkey = p_resp->mr.lkey;\r
241                                 page->mr.rkey = p_resp->mr.rkey;\r
242                                 page->mr.pd = p_pd->ibv_pd;\r
243                                 page->mr.context = p_pd->ibv_pd->context;\r
244                         }\r
245                         ah->key  = page->mr.lkey;\r
246                 }\r
247                 *ph_uvp_av = (ib_av_handle_t)ah;\r
248         }\r
249         else {\r
250                 mthca_free_av(ah);\r
251                 cl_free(ah);\r
252         }\r
253         goto end;\r
254         \r
255 end:    \r
256         if (p_resp)\r
257                 cl_free( p_resp );\r
258         UVP_EXIT(UVP_DBG_AV);\r
259 }\r
260 \r
261 static ib_api_status_t\r
262 __pre_query_av (\r
263         IN      const   ib_av_handle_t          h_uvp_av,\r
264         IN OUT          ci_umv_buf_t            *p_umv_buf )\r
265 {\r
266         UNREFERENCED_PARAMETER(h_uvp_av);\r
267         UNREFERENCED_PARAMETER(p_umv_buf);\r
268         UVP_ENTER(UVP_DBG_AV);\r
269         UVP_EXIT(UVP_DBG_AV);\r
270         return IB_VERBS_PROCESSING_DONE;\r
271 }\r
272 \r
273 \r
274 static void\r
275 __post_query_av (\r
276         IN              const   ib_av_handle_t                          h_uvp_av,\r
277         IN                              ib_api_status_t                         ioctl_status,\r
278         IN      OUT                     ib_av_attr_t                            *p_addr_vector,\r
279         IN      OUT                     ib_pd_handle_t                          *ph_pd,\r
280         IN      OUT                     ci_umv_buf_t                            *p_umv_buf)\r
281 {\r
282         struct mthca_ah *ah = (struct mthca_ah *)h_uvp_av;\r
283         UNREFERENCED_PARAMETER(p_umv_buf);\r
284 \r
285         UVP_ENTER(UVP_DBG_AV);\r
286         CL_ASSERT(p_umv_buf);\r
287         CL_ASSERT(p_addr_vector);\r
288 \r
289         if (ioctl_status == IB_SUCCESS)\r
290         {\r
291                 cl_memcpy (p_addr_vector, &ah->av_attr, sizeof (ib_av_attr_t));\r
292                 if (ph_pd)\r
293                         *ph_pd = (ib_pd_handle_t)ah->h_uvp_pd;\r
294         }\r
295         \r
296         UVP_EXIT(UVP_DBG_AV);\r
297 }\r
298 \r
299 void mthca_set_av_params( struct mthca_ah *ah_p, struct ibv_ah_attr *ah_attr );\r
300 \r
301 static ib_api_status_t\r
302 __pre_modify_av (\r
303         IN              const ib_av_handle_t    h_uvp_av,\r
304         IN              const ib_av_attr_t              *p_addr_vector,\r
305         IN OUT  ci_umv_buf_t                    *p_umv_buf)\r
306 {\r
307         ib_api_status_t status ;\r
308         struct mthca_ah *mthca_ah = (struct mthca_ah *)h_uvp_av;\r
309         mlnx_ual_pd_info_t *p_pd_info;\r
310         mlnx_ual_hobul_t *p_hobul;\r
311         struct ibv_ah_attr attr;\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 = mthca_ah->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 (&mthca_ah->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 static void\r
337 __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 }\r
345 \r
346 \r
347 static ib_api_status_t\r
348 __pre_destroy_av (\r
349         IN              const ib_av_handle_t            h_uvp_av)\r
350 {\r
351         ib_api_status_t status ;\r
352         struct mthca_ah *mthca_ah = (struct mthca_ah *)h_uvp_av;\r
353         UVP_ENTER(UVP_DBG_AV);\r
354         if (mthca_ah->in_kernel)\r
355                 status = IB_SUCCESS;\r
356         else\r
357                 status = IB_VERBS_PROCESSING_DONE;\r
358         UVP_EXIT(UVP_DBG_AV);\r
359         return status;\r
360 }\r
361 \r
362 static void\r
363 __post_destroy_av (\r
364         IN              const ib_av_handle_t            h_uvp_av,\r
365         IN              ib_api_status_t                 ioctl_status)\r
366 {\r
367         struct mthca_ah *mthca_ah = (struct mthca_ah *)h_uvp_av;\r
368 \r
369         UVP_ENTER(UVP_DBG_AV);\r
370         CL_ASSERT (h_uvp_av);\r
371 \r
372         if (IB_SUCCESS == ioctl_status) {\r
373                 mthca_free_av(mthca_ah);\r
374                 cl_free(mthca_ah);\r
375         }\r
376 \r
377         UVP_EXIT(UVP_DBG_AV);\r
378         return;\r
379 }\r
380 \r
381 void\r
382 mlnx_get_av_interface (\r
383         IN OUT  uvp_interface_t         *p_uvp )\r
384 {\r
385 \r
386         CL_ASSERT(p_uvp);\r
387 \r
388         /*\r
389          * Address Vector Management Verbs\r
390          */\r
391         p_uvp->pre_create_av  = __pre_create_av;\r
392         p_uvp->post_create_av = __post_create_av;\r
393         p_uvp->pre_query_av   = __pre_query_av;\r
394         p_uvp->post_query_av  = __post_query_av;\r
395         p_uvp->pre_modify_av   = __pre_modify_av;\r
396         p_uvp->post_modify_av  = __post_modify_av;\r
397         p_uvp->pre_destroy_av  = __pre_destroy_av;\r
398         p_uvp->post_destroy_av = __post_destroy_av;\r
399 \r
400 }\r
401 \r