[MT23108] Removed linker dependency on IBAL.
[mirror/winof/.git] / hw / mt23108 / kernel / hca_memory.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$\r
31  */\r
32 \r
33 \r
34 #include "hca_data.h"\r
35 \r
36 /*\r
37  *      Memory Management Verbs.\r
38  */\r
39 \r
40 ib_api_status_t\r
41 mlnx_register_mr (\r
42         IN              const   ib_pd_handle_t                          h_pd,\r
43         IN              const   ib_mr_create_t                          *p_mr_create,\r
44                 OUT                     net32_t* const                          p_lkey,\r
45                 OUT                     net32_t* const                          p_rkey,\r
46                 OUT                     ib_mr_handle_t                          *ph_mr,\r
47         IN                              boolean_t                                       um_call )\r
48 {\r
49         u_int32_t                       hca_idx = PD_HCA_FROM_HNDL(h_pd);\r
50         u_int32_t                       pd_idx  = PD_NUM_FROM_HNDL(h_pd);\r
51         mlnx_hobul_t            *hobul_p;\r
52         ib_api_status_t         status;\r
53 \r
54         HH_mr_t                         mr_props;\r
55         mlnx_mro_t                      *mro_p = NULL;\r
56         u_int32_t                       lkey=0, rkey=0;\r
57 \r
58         CL_ENTER(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
59 \r
60         if( !cl_is_blockable() )\r
61                 return IB_UNSUPPORTED;\r
62 \r
63         VALIDATE_INDEX(hca_idx, MLNX_MAX_HCA, IB_INVALID_PD_HANDLE, cleanup);\r
64         hobul_p = mlnx_hobul_array[hca_idx];\r
65         if (NULL == hobul_p) {\r
66                 status = IB_INVALID_PD_HANDLE;\r
67                 goto cleanup;\r
68         }\r
69         VALIDATE_INDEX(pd_idx, hobul_p->max_pd, IB_INVALID_PD_HANDLE, cleanup);\r
70         if (E_MARK_PD != hobul_p->pd_info_tbl[pd_idx].mark) {\r
71                 status =  IB_INVALID_PD_HANDLE;\r
72                 goto cleanup;\r
73         }\r
74 \r
75         if (!p_mr_create || 0 == p_mr_create->length) {\r
76                 status = IB_INVALID_PARAMETER;\r
77                 goto cleanup; \r
78         }\r
79 \r
80         if (NULL == (mro_p = cl_zalloc( sizeof(mlnx_mro_t)))) {\r
81                 status = IB_INSUFFICIENT_MEMORY;\r
82                 goto cleanup; \r
83         }\r
84 \r
85         // Convert MR properties (LOCKS THE REGION as a side effect)\r
86         cl_memclr(&mr_props, sizeof(HH_mr_t));\r
87         status = mlnx_conv_ibal_mr_create(pd_idx, mro_p,\r
88                 VAPI_MR_CHANGE_TRANS | VAPI_MR_CHANGE_PD | VAPI_MR_CHANGE_ACL,\r
89                 p_mr_create, um_call, &mr_props);\r
90         if (status != IB_SUCCESS ) {\r
91                 goto cleanup;\r
92         }\r
93 \r
94         // Register MR\r
95         if (HH_OK != THH_hob_register_mr(hobul_p->hh_hndl, &mr_props, &lkey, &rkey)) {\r
96                 status = IB_ERROR;\r
97                 goto cleanup_post_lock;\r
98         }\r
99 \r
100         if (p_lkey) *p_lkey = lkey;\r
101         if (p_rkey) *p_rkey = cl_hton32( rkey );\r
102 \r
103         // update PD object count\r
104         cl_atomic_inc(&hobul_p->pd_info_tbl[pd_idx].count);\r
105 \r
106         mro_p->mark = E_MARK_MR;\r
107         mro_p->mr_type = E_MR_ANY;\r
108         mro_p->mr_pd_handle = PD_HNDL_FROM_PD(pd_idx);\r
109         mro_p->mr_lkey = lkey;\r
110         if (ph_mr) *ph_mr = (ib_mr_handle_t)mro_p;\r
111 \r
112         CL_EXIT(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
113         return IB_SUCCESS;\r
114 \r
115 cleanup_post_lock:\r
116         MOSAL_iobuf_deregister(mro_p->mr_iobuf);\r
117 \r
118 cleanup:\r
119         if (mro_p) {\r
120                 mro_p->mark = E_MARK_INVALID;\r
121                 cl_free( mro_p);\r
122         }\r
123         CL_TRACE(CL_DBG_ERROR, g_mlnx_dbg_lvl, ("file %s line %d\n", __FILE__, __LINE__));\r
124         CL_TRACE(CL_DBG_ERROR, g_mlnx_dbg_lvl, ("completes with ERROR status %d\n", status));\r
125         CL_EXIT(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
126         return status;\r
127 }\r
128 \r
129 ib_api_status_t\r
130 mlnx_register_pmr (\r
131         IN              const   ib_pd_handle_t                          h_pd,\r
132         IN              const   ib_phys_create_t* const         p_pmr_create,\r
133         IN      OUT                     uint64_t* const                         p_vaddr,\r
134                 OUT                     net32_t* const                          p_lkey,\r
135                 OUT                     net32_t* const                          p_rkey,\r
136                 OUT                     ib_mr_handle_t* const           ph_mr,\r
137         IN                              boolean_t                                       um_call )\r
138 {\r
139         u_int32_t                       hca_idx = PD_HCA_FROM_HNDL(h_pd);\r
140         u_int32_t                       pd_idx  = PD_NUM_FROM_HNDL(h_pd);\r
141         mlnx_hobul_t            *hobul_p;\r
142         ib_api_status_t         status;\r
143 \r
144         HH_mr_t                         mr_props = { 0 };\r
145         mlnx_mro_t                      *mro_p = NULL;\r
146         u_int32_t                       lkey, rkey;\r
147 \r
148         UNUSED_PARAM( um_call );\r
149 \r
150         CL_ENTER(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
151 \r
152         if( !cl_is_blockable() )\r
153                 return IB_UNSUPPORTED;\r
154 \r
155         VALIDATE_INDEX(hca_idx, MLNX_MAX_HCA, IB_INVALID_PD_HANDLE, cleanup);\r
156         hobul_p = mlnx_hobul_array[hca_idx];\r
157         if (NULL == hobul_p) {\r
158                 status = IB_INVALID_PD_HANDLE;\r
159                 goto cleanup;\r
160         }\r
161 \r
162         VALIDATE_INDEX(pd_idx, hobul_p->max_pd, IB_INVALID_PD_HANDLE, cleanup);\r
163         if (E_MARK_PD != hobul_p->pd_info_tbl[pd_idx].mark) {\r
164                 status =  IB_INVALID_PD_HANDLE;\r
165                 goto cleanup;\r
166         }\r
167 \r
168         if (!p_vaddr || !p_pmr_create ||\r
169                 0 == p_pmr_create->length ) {\r
170                         status = IB_INVALID_PARAMETER;\r
171                         goto cleanup; \r
172                 }\r
173 \r
174                 mro_p = cl_zalloc( sizeof(mlnx_mro_t));\r
175                 if ( !mro_p ) {\r
176                         status = IB_INSUFFICIENT_MEMORY;\r
177                         goto cleanup; \r
178                 }\r
179 \r
180                 // Convert PMR properties\r
181                 mro_p->mr_start = *p_vaddr;\r
182                 cl_memclr(&mr_props, sizeof(HH_mr_t));\r
183                 status = mlnx_conv_ibal_pmr_create( pd_idx, mro_p, p_pmr_create,\r
184                         &mr_props );\r
185                 if (status != IB_SUCCESS ) {\r
186                         goto cleanup;\r
187                 }\r
188 \r
189                 // Register MR\r
190                 if (HH_OK != THH_hob_register_mr( hobul_p->hh_hndl, &mr_props,\r
191                         &lkey, &rkey )) {\r
192                         status = IB_ERROR;\r
193                         goto cleanup;\r
194                 }\r
195                 if (p_lkey) *p_lkey = lkey;\r
196                 if (p_rkey) *p_rkey = cl_hton32( rkey );\r
197 \r
198                 if( mr_props.tpt.tpt.buf_lst.buf_sz_lst )\r
199                         cl_free( mr_props.tpt.tpt.buf_lst.buf_sz_lst );\r
200 \r
201                 if( mr_props.tpt.tpt.buf_lst.phys_buf_lst )\r
202                         cl_free( mr_props.tpt.tpt.buf_lst.phys_buf_lst );\r
203 \r
204                 // update PD object count\r
205                 cl_atomic_inc(&hobul_p->pd_info_tbl[pd_idx].count);\r
206 \r
207                 mro_p->mark = E_MARK_MR;\r
208                 mro_p->mr_type = E_MR_PHYS;\r
209                 mro_p->mr_pd_handle = PD_HNDL_FROM_PD(pd_idx);\r
210                 mro_p->mr_lkey = lkey;\r
211                 if (ph_mr) *ph_mr = (ib_mr_handle_t)mro_p;\r
212                 *p_vaddr = mro_p->mr_start; // return the updated address\r
213 \r
214                 CL_TRACE(MLNX_DBG_MEM, g_mlnx_dbg_lvl, ("file %s line %d\n", __FILE__, __LINE__));\r
215                 CL_TRACE(MLNX_DBG_MEM, g_mlnx_dbg_lvl, ("mro_p 0x%p mark %d\n", mro_p, (mro_p ? mro_p->mark : 0xBAD)));\r
216                 CL_EXIT(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
217                 return IB_SUCCESS;\r
218 \r
219 cleanup:\r
220                 if( mr_props.tpt.tpt.buf_lst.buf_sz_lst )\r
221                         cl_free( mr_props.tpt.tpt.buf_lst.buf_sz_lst );\r
222 \r
223                 if( mr_props.tpt.tpt.buf_lst.phys_buf_lst )\r
224                         cl_free( mr_props.tpt.tpt.buf_lst.phys_buf_lst );\r
225 \r
226                 if (mro_p) {\r
227                         mro_p->mark = E_MARK_INVALID;\r
228                         cl_free( mro_p);\r
229                 }\r
230                 CL_TRACE(CL_DBG_ERROR, g_mlnx_dbg_lvl, ("completes with ERROR status %d\n", status));\r
231                 CL_EXIT(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
232                 return status;\r
233 }\r
234 \r
235 ib_api_status_t\r
236 mlnx_query_mr (\r
237         IN              const   ib_mr_handle_t                          h_mr,\r
238                 OUT                     ib_mr_attr_t                            *p_mr_query )\r
239 {\r
240         u_int32_t        hca_idx;\r
241         u_int32_t        pd_idx;\r
242         mlnx_hobul_t     *hobul_p;\r
243         ib_api_status_t  status = IB_SUCCESS;\r
244 \r
245         HH_mr_info_t     mr_info;\r
246         mlnx_mro_t       *mro_p = NULL;\r
247 \r
248         CL_ENTER(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
249 \r
250         if( !cl_is_blockable() )\r
251                 return IB_UNSUPPORTED;\r
252 \r
253         mro_p = (mlnx_mro_t *)h_mr;\r
254         if (!mro_p || mro_p->mark != E_MARK_MR) {\r
255                 status = IB_INVALID_MR_HANDLE;\r
256                 goto cleanup;\r
257         }\r
258 \r
259         hca_idx = PD_HCA_FROM_HNDL(mro_p->mr_pd_handle);\r
260         pd_idx  = PD_NUM_FROM_HNDL(mro_p->mr_pd_handle);\r
261 \r
262         VALIDATE_INDEX(hca_idx, MLNX_MAX_HCA, IB_INVALID_MR_HANDLE, cleanup);\r
263         hobul_p = mlnx_hobul_array[hca_idx];\r
264         if (NULL == hobul_p) {\r
265                 status = IB_INVALID_PARAMETER;\r
266                 goto cleanup;\r
267         }\r
268         VALIDATE_INDEX(pd_idx, hobul_p->max_pd, IB_INVALID_MR_HANDLE, cleanup);\r
269         if (E_MARK_PD != hobul_p->pd_info_tbl[pd_idx].mark) {\r
270                 status =  IB_INVALID_PD_HANDLE;\r
271                 goto cleanup;\r
272         }\r
273         CL_TRACE(MLNX_DBG_MEM, g_mlnx_dbg_lvl, ("file %s line %d\n", __FILE__, __LINE__));\r
274         CL_TRACE(MLNX_DBG_MEM, g_mlnx_dbg_lvl, ("mro_p 0x%p mark %d\n", mro_p, (mro_p ? mro_p->mark : 0xBAD)));\r
275 \r
276         if (HH_OK != THH_hob_query_mr(hobul_p->hh_hndl, mro_p->mr_lkey, &mr_info)) {\r
277                 status = IB_ERROR;\r
278                 goto cleanup;\r
279         }\r
280 \r
281         mlnx_conv_vapi_mr_attr((ib_pd_handle_t)PD_HNDL_FROM_PD(pd_idx), &mr_info, p_mr_query);\r
282 \r
283         CL_EXIT(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
284         return IB_SUCCESS;\r
285 \r
286 cleanup:\r
287         CL_TRACE(CL_DBG_ERROR, g_mlnx_dbg_lvl, ("completes with ERROR status %d\n", status));\r
288         CL_EXIT(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
289         return status;\r
290 }\r
291 \r
292 \r
293 ib_api_status_t\r
294 mlnx_modify_mr (\r
295         IN              const   ib_mr_handle_t                          h_mr,\r
296         IN              const   ib_mr_mod_t                                     mem_modify_req,\r
297         IN              const   ib_mr_create_t                          *p_mr_create,\r
298                 OUT                     uint32_t                                        *p_lkey,\r
299                 OUT                     uint32_t                                        *p_rkey,\r
300         IN              const   ib_pd_handle_t                          h_pd OPTIONAL,\r
301         IN                              boolean_t                                       um_call )\r
302 {\r
303         u_int32_t                       hca_idx;\r
304         u_int32_t                       pd_idx, old_pd_idx;\r
305         mlnx_hobul_t            *hobul_p;\r
306         ib_api_status_t         status;\r
307 \r
308         VAPI_mr_change_t        change_mask;\r
309         HH_mr_t                         mr_props;\r
310         mlnx_mro_t                      *mro_p = NULL;\r
311         u_int32_t                       lkey, rkey;\r
312 \r
313         CL_ENTER(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
314 \r
315         if( !cl_is_blockable() )\r
316                 return IB_UNSUPPORTED;\r
317 \r
318         mro_p = (mlnx_mro_t *)h_mr;\r
319         if (!mro_p || mro_p->mark != E_MARK_MR) {\r
320                 status = IB_INVALID_MR_HANDLE;\r
321                 goto cleanup;\r
322         }\r
323 \r
324         if ( !p_mr_create || 0 == p_mr_create->length ||\r
325                 !p_lkey || !p_rkey)\r
326         {\r
327                 status = IB_INVALID_PARAMETER;\r
328                 goto cleanup;\r
329         }\r
330 \r
331         if( (mem_modify_req & IB_MR_MOD_PD) && !h_pd )\r
332         {\r
333                 status = IB_INVALID_PD_HANDLE;\r
334                 goto cleanup;\r
335         }\r
336 \r
337         hca_idx = PD_HCA_FROM_HNDL(mro_p->mr_pd_handle);\r
338         if( (mem_modify_req & IB_MR_MOD_PD) && h_pd )\r
339                 pd_idx = PD_NUM_FROM_HNDL(h_pd);\r
340         else\r
341                 pd_idx = PD_NUM_FROM_HNDL(mro_p->mr_pd_handle);\r
342 \r
343         old_pd_idx = PD_NUM_FROM_HNDL(mro_p->mr_pd_handle);\r
344 \r
345         VALIDATE_INDEX(hca_idx, MLNX_MAX_HCA, IB_INVALID_MR_HANDLE, cleanup);\r
346         hobul_p = mlnx_hobul_array[hca_idx];\r
347         if (NULL == hobul_p) {\r
348                 status = IB_INVALID_PARAMETER;\r
349                 goto cleanup;\r
350         }\r
351         VALIDATE_INDEX(pd_idx, hobul_p->max_pd, IB_INVALID_MR_HANDLE, cleanup);\r
352         if (E_MARK_PD != hobul_p->pd_info_tbl[pd_idx].mark) {\r
353                 status =  IB_INVALID_PD_HANDLE;\r
354                 goto cleanup;\r
355         }\r
356 \r
357         CL_TRACE(MLNX_DBG_MEM, g_mlnx_dbg_lvl, ("file %s line %d\n", __FILE__, __LINE__));\r
358         CL_TRACE(MLNX_DBG_MEM, g_mlnx_dbg_lvl, ("mro_p 0x%p mark %d\n", mro_p, (mro_p ? mro_p->mark : 0xBAD)));\r
359 \r
360         // change_mask = mem_modify_req;\r
361         change_mask = 0;\r
362         if (mem_modify_req & IB_MR_MOD_ADDR) change_mask |= VAPI_MR_CHANGE_TRANS;\r
363         if (mem_modify_req & IB_MR_MOD_PD)    change_mask |= VAPI_MR_CHANGE_PD;\r
364         if (mem_modify_req & IB_MR_MOD_ACCESS) change_mask |= VAPI_MR_CHANGE_ACL;\r
365 \r
366         cl_memclr(&mr_props, sizeof(HH_mr_t));\r
367         status = mlnx_conv_ibal_mr_create(pd_idx, mro_p, change_mask, p_mr_create,\r
368                 um_call, &mr_props);\r
369         if ( status != IB_SUCCESS ) {\r
370                 goto cleanup;\r
371         }\r
372 \r
373         if (HH_OK != THH_hob_reregister_mr(hobul_p->hh_hndl,\r
374                 mro_p->mr_lkey,\r
375                 change_mask,\r
376                 &mr_props, \r
377                 &lkey, &rkey))\r
378         {\r
379                 status = IB_ERROR;\r
380                 goto cleanup;\r
381         }\r
382 \r
383         // update PD object count\r
384         if( (mem_modify_req & IB_MR_MOD_PD) && h_pd )\r
385         {\r
386                 mro_p->mr_pd_handle = PD_HNDL_FROM_PD( pd_idx );\r
387                 cl_atomic_inc(&hobul_p->pd_info_tbl[pd_idx].count);\r
388                 cl_atomic_dec(&hobul_p->pd_info_tbl[old_pd_idx].count);\r
389         }\r
390 \r
391         // Update our "shadow" (TBD: old memory region may need to be unlocked)\r
392         mro_p->mr_lkey = lkey;\r
393 \r
394         // Return new keys to the caller\r
395         if (p_lkey) *p_lkey = lkey;\r
396         if (p_rkey) *p_rkey = rkey;\r
397 \r
398         CL_EXIT(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
399         return IB_SUCCESS;\r
400 \r
401 cleanup:\r
402         CL_TRACE(CL_DBG_ERROR, g_mlnx_dbg_lvl, ("completes with ERROR status %d\n", status));\r
403         CL_EXIT(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
404         return status;\r
405 }\r
406 \r
407 \r
408 ib_api_status_t\r
409 mlnx_modify_pmr (\r
410         IN              const   ib_mr_handle_t                          h_mr,\r
411         IN              const   ib_mr_mod_t                                     mem_modify_req,\r
412         IN              const   ib_phys_create_t* const         p_pmr_create,\r
413         IN      OUT                     uint64_t* const                         p_vaddr,\r
414                 OUT                     uint32_t* const                         p_lkey,\r
415                 OUT                     uint32_t* const                         p_rkey,\r
416         IN              const   ib_pd_handle_t                          h_pd OPTIONAL,\r
417         IN                              boolean_t                                       um_call )\r
418 {\r
419         u_int32_t        hca_idx;\r
420         u_int32_t        pd_idx;\r
421         mlnx_hobul_t     *hobul_p;\r
422         ib_api_status_t  status;\r
423 \r
424         VAPI_mr_change_t change_mask;\r
425         HH_mr_t          mr_props = { 0 };\r
426         mlnx_mro_t       *mro_p = NULL;\r
427         u_int32_t        lkey, rkey;\r
428 \r
429         UNUSED_PARAM( um_call );\r
430 \r
431         CL_ENTER(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
432 \r
433         if( !cl_is_blockable() )\r
434                 return IB_UNSUPPORTED;\r
435 \r
436         mro_p = (mlnx_mro_t *)h_mr;\r
437         if (!mro_p || mro_p->mark != E_MARK_MR) {\r
438                 status = IB_INVALID_MR_HANDLE;\r
439                 goto cleanup;\r
440         }\r
441 \r
442         if ( !p_pmr_create || 0 == p_pmr_create->length ||\r
443                 !p_lkey || !p_rkey)\r
444         {\r
445                 status = IB_INVALID_PARAMETER;\r
446                 goto cleanup;\r
447         }\r
448 \r
449         hca_idx = PD_HCA_FROM_HNDL(mro_p->mr_pd_handle);\r
450         if( h_pd )\r
451                 pd_idx = PD_NUM_FROM_HNDL( h_pd );\r
452         else\r
453                 pd_idx  = PD_NUM_FROM_HNDL(mro_p->mr_pd_handle);\r
454 \r
455         VALIDATE_INDEX(hca_idx, MLNX_MAX_HCA, IB_INVALID_MR_HANDLE, cleanup);\r
456         hobul_p = mlnx_hobul_array[hca_idx];\r
457         if (NULL == hobul_p) {\r
458                 status = IB_INVALID_PARAMETER;\r
459                 goto cleanup;\r
460         }\r
461         VALIDATE_INDEX(pd_idx, hobul_p->max_pd, IB_INVALID_MR_HANDLE, cleanup);\r
462         if (E_MARK_PD != hobul_p->pd_info_tbl[pd_idx].mark) {\r
463                 status =  IB_INVALID_PD_HANDLE;\r
464                 goto cleanup;\r
465         }\r
466 \r
467         // change_mask = mem_modify_req;\r
468         change_mask = 0;\r
469         if (mem_modify_req & IB_MR_MOD_ADDR) change_mask |= VAPI_MR_CHANGE_TRANS;\r
470         if (mem_modify_req & IB_MR_MOD_PD)    change_mask |= VAPI_MR_CHANGE_PD;\r
471         if (mem_modify_req & IB_MR_MOD_ACCESS) change_mask |= VAPI_MR_CHANGE_ACL;\r
472 \r
473         // Convert PMR properties\r
474         mro_p->mr_start = *p_vaddr;\r
475         cl_memclr(&mr_props, sizeof(HH_mr_t));\r
476         if (IB_SUCCESS != (status = mlnx_conv_ibal_pmr_create(pd_idx, mro_p, p_pmr_create, &mr_props))) {\r
477                 goto cleanup;\r
478         }\r
479 \r
480         if (HH_OK != THH_hob_reregister_mr(hobul_p->hh_hndl,\r
481                 mro_p->mr_lkey,\r
482                 change_mask,\r
483                 &mr_props, \r
484                 &lkey, &rkey))\r
485         {\r
486                 status = IB_ERROR;\r
487                 goto cleanup;\r
488         }\r
489 \r
490         if( mr_props.tpt.tpt.buf_lst.buf_sz_lst )\r
491                 cl_free( mr_props.tpt.tpt.buf_lst.buf_sz_lst );\r
492 \r
493         if( mr_props.tpt.tpt.buf_lst.phys_buf_lst )\r
494                 cl_free( mr_props.tpt.tpt.buf_lst.phys_buf_lst );\r
495 \r
496         // Update our "shadow"\r
497         mro_p->mr_lkey = lkey;\r
498 \r
499         // Return new keys to the caller\r
500         if (p_lkey) *p_lkey = lkey;\r
501         if (p_rkey) *p_rkey = rkey;\r
502 \r
503         CL_EXIT(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
504         return IB_SUCCESS;\r
505 \r
506 cleanup:\r
507         if( mr_props.tpt.tpt.buf_lst.buf_sz_lst )\r
508                 cl_free( mr_props.tpt.tpt.buf_lst.buf_sz_lst );\r
509 \r
510         if( mr_props.tpt.tpt.buf_lst.phys_buf_lst )\r
511                 cl_free( mr_props.tpt.tpt.buf_lst.phys_buf_lst );\r
512 \r
513         CL_TRACE(CL_DBG_ERROR, g_mlnx_dbg_lvl, ("completes with ERROR status %d\n", status));\r
514         CL_EXIT(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
515         return status;\r
516 }\r
517 \r
518 ib_api_status_t\r
519 mlnx_register_smr (\r
520         IN              const   ib_mr_handle_t                          h_mr,\r
521         IN              const   ib_pd_handle_t                          h_pd,\r
522         IN              const   ib_access_t                                     access_ctrl,\r
523         IN      OUT                     uint64_t* const                         p_vaddr,\r
524                 OUT                     net32_t* const                          p_lkey,\r
525                 OUT                     net32_t* const                          p_rkey,\r
526                 OUT                     ib_mr_handle_t* const           ph_mr,\r
527         IN                              boolean_t                                       um_call )\r
528 {\r
529         u_int32_t                       hca_idx = PD_HCA_FROM_HNDL(h_pd);\r
530         u_int32_t                       pd_idx  = PD_NUM_FROM_HNDL(h_pd);\r
531         mlnx_hobul_t            *hobul_p;\r
532         ib_api_status_t         status;\r
533 \r
534         HH_smr_t                        smr_props;\r
535         mlnx_mro_t                      *base_mro_p = NULL;\r
536         mlnx_mro_t                      *new_mro_p = NULL;\r
537         u_int32_t                       lkey, rkey;\r
538 \r
539         CL_ENTER(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
540 \r
541         if( !cl_is_blockable() )\r
542                 return IB_UNSUPPORTED;\r
543 \r
544         VALIDATE_INDEX(hca_idx, MLNX_MAX_HCA, IB_INVALID_PD_HANDLE, cleanup);\r
545         hobul_p = mlnx_hobul_array[hca_idx];\r
546         if (NULL == hobul_p) {\r
547                 status = IB_INVALID_PD_HANDLE;\r
548                 goto cleanup;\r
549         }\r
550         VALIDATE_INDEX(pd_idx, hobul_p->max_pd, IB_INVALID_PD_HANDLE, cleanup);\r
551         if (E_MARK_PD != hobul_p->pd_info_tbl[pd_idx].mark) {\r
552                 status =  IB_INVALID_PD_HANDLE;\r
553                 goto cleanup;\r
554         }\r
555 \r
556         if (!ph_mr || !p_vaddr || !p_lkey || !p_rkey ) {\r
557                 status = IB_INVALID_PARAMETER;\r
558                 goto cleanup; \r
559         }\r
560 \r
561         base_mro_p = (mlnx_mro_t *)h_mr;\r
562         if (!base_mro_p || base_mro_p->mark != E_MARK_MR) {\r
563                 status = IB_INVALID_MR_HANDLE;\r
564                 goto cleanup;\r
565         }\r
566 \r
567         // Convert SMR properties\r
568         smr_props.lkey = base_mro_p->mr_lkey; // L-Key of the region to share with\r
569         // This region start virtual addr\r
570         smr_props.start = *p_vaddr;\r
571         // PD handle for new memory region\r
572         smr_props.pd = PD_NUM_FROM_HNDL(base_mro_p->mr_pd_handle);\r
573         smr_props.acl = map_ibal_acl(access_ctrl); // Access control (R/W permission local/remote\r
574 \r
575         // Allocate new handle for shared region\r
576         if (NULL == (new_mro_p = cl_zalloc( sizeof(mlnx_mro_t)))) {\r
577                 status = IB_INSUFFICIENT_MEMORY;\r
578                 goto cleanup; \r
579         }\r
580 \r
581         new_mro_p->mr_start = *p_vaddr;\r
582         new_mro_p->mr_size = base_mro_p->mr_size;\r
583 \r
584         // This computation should be externalized by THH\r
585         new_mro_p->mr_mosal_perm =\r
586                 MOSAL_PERM_READ |\r
587                 ((smr_props.acl & VAPI_EN_LOCAL_WRITE) ? MOSAL_PERM_WRITE : 0);\r
588 \r
589         if (IB_SUCCESS != (status = mlnx_lock_region(new_mro_p, um_call ))) {\r
590                 goto cleanup;\r
591         }\r
592 \r
593         // Register MR\r
594         if (HH_OK != THH_hob_register_smr(hobul_p->hh_hndl, &smr_props, &lkey, &rkey)) {\r
595                 status = IB_ERROR;\r
596                 goto cleanup;\r
597         }\r
598 \r
599         // Return modified values\r
600         *p_vaddr = smr_props.start;\r
601         *p_lkey = lkey;\r
602         *p_rkey = cl_hton32( rkey );\r
603 \r
604         // update PD object count\r
605         cl_atomic_inc(&hobul_p->pd_info_tbl[pd_idx].count);\r
606 \r
607         new_mro_p->mark = E_MARK_MR;\r
608         new_mro_p->mr_type = E_MR_SHARED;\r
609         new_mro_p->mr_pd_handle = PD_HNDL_FROM_PD(pd_idx);\r
610         new_mro_p->mr_lkey = lkey;\r
611 \r
612         *ph_mr = (ib_mr_handle_t)new_mro_p;\r
613 \r
614 //      CL_TRACE(MLNX_DBG_INFO, g_mlnx_dbg_lvl, ("new_mro_p 0x%p page 0x%x, %d\n",\r
615 //              new_mro_p, new_mro_p->mr_first_page_addr, new_mro_p->mr_num_pages));\r
616         CL_EXIT(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
617         return IB_SUCCESS;\r
618 \r
619 cleanup:\r
620         if (new_mro_p) {\r
621                 new_mro_p->mark = E_MARK_INVALID;\r
622                 cl_free( new_mro_p);\r
623         }\r
624         CL_TRACE(CL_DBG_ERROR, g_mlnx_dbg_lvl, ("completes with ERROR status %d\n", status));\r
625         CL_EXIT(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
626         return status;\r
627 }\r
628 \r
629 ib_api_status_t\r
630 mlnx_deregister_mr (\r
631         IN              const   ib_mr_handle_t                          h_mr)\r
632 {\r
633         mlnx_mro_t                      *mro_p = NULL;\r
634         u_int32_t                       hca_idx;\r
635         u_int32_t                       pd_idx;\r
636         mlnx_hobul_t            *hobul_p;\r
637         ib_api_status_t         status;\r
638 \r
639         CL_ENTER(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
640 \r
641         if( !cl_is_blockable() )\r
642                 return IB_UNSUPPORTED;\r
643 \r
644         mro_p = (mlnx_mro_t *)h_mr;\r
645         if (!mro_p || mro_p->mark != E_MARK_MR) {\r
646                 CL_TRACE(CL_DBG_ERROR, g_mlnx_dbg_lvl, ("file %s line %d\n", __FILE__, __LINE__));\r
647                 CL_TRACE(CL_DBG_ERROR, g_mlnx_dbg_lvl, ("mro_p 0x%p mark %d\n", mro_p, (mro_p ? mro_p->mark : 0xBAD)));\r
648                 status = IB_INVALID_MR_HANDLE;\r
649                 goto cleanup;\r
650         }\r
651 \r
652         hca_idx = PD_HCA_FROM_HNDL(mro_p->mr_pd_handle);\r
653         pd_idx  = PD_NUM_FROM_HNDL(mro_p->mr_pd_handle);\r
654 \r
655         VALIDATE_INDEX(hca_idx, MLNX_MAX_HCA, IB_INVALID_MR_HANDLE, cleanup);\r
656         hobul_p = mlnx_hobul_array[hca_idx];\r
657         if (NULL == hobul_p) {\r
658                 status = IB_INVALID_PARAMETER;\r
659                 goto cleanup;\r
660         }\r
661         VALIDATE_INDEX(pd_idx, hobul_p->max_pd, IB_INVALID_MR_HANDLE, cleanup);\r
662         if (E_MARK_PD != hobul_p->pd_info_tbl[pd_idx].mark) {\r
663                 status =  IB_INVALID_PD_HANDLE;\r
664                 goto cleanup;\r
665         }\r
666 \r
667         THH_hob_deregister_mr(hobul_p->hh_hndl, mro_p->mr_lkey);\r
668 \r
669         if (mro_p->mr_type != E_MR_PHYS) {\r
670                 MOSAL_iobuf_deregister(mro_p->mr_iobuf);\r
671         }\r
672 \r
673         // update PD object count\r
674         cl_atomic_dec(&hobul_p->pd_info_tbl[pd_idx].count);\r
675         CL_TRACE(MLNX_DBG_INFO, g_mlnx_dbg_lvl, ("pd %d count %d\n", pd_idx, hobul_p->pd_info_tbl[pd_idx].count));\r
676 \r
677         if (mro_p) {\r
678                 mro_p->mark = E_MARK_INVALID;\r
679                 cl_free( mro_p);\r
680         }\r
681         CL_EXIT(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
682         return IB_SUCCESS;\r
683 \r
684 cleanup:\r
685         if (mro_p) {\r
686                 mro_p->mark = E_MARK_INVALID;\r
687                 cl_free( mro_p);\r
688         }\r
689         CL_TRACE(CL_DBG_ERROR, g_mlnx_dbg_lvl, ("completes with ERROR status %d\n", status));\r
690         CL_EXIT(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
691         return status;\r
692 }\r
693 \r
694 /*\r
695 *       Memory Window Verbs.\r
696 */\r
697 \r
698 ib_api_status_t\r
699 mlnx_create_mw (\r
700         IN              const   ib_pd_handle_t                          h_pd,\r
701                 OUT                     net32_t* const                          p_rkey,\r
702                 OUT                     ib_mw_handle_t                          *ph_mw,\r
703         IN      OUT                     ci_umv_buf_t                            *p_umv_buf )\r
704 {\r
705         u_int32_t                       hca_idx = PD_HCA_FROM_HNDL(h_pd);\r
706         u_int32_t                       pd_idx  = PD_NUM_FROM_HNDL(h_pd);\r
707         mlnx_hobul_t            *hobul_p;\r
708         mlnx_mwo_t                      *mwo_p = NULL;\r
709         ib_api_status_t         status;\r
710 \r
711         CL_ENTER(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
712 \r
713         if( !cl_is_blockable() )\r
714                 return IB_UNSUPPORTED;\r
715 \r
716         VALIDATE_INDEX(hca_idx, MLNX_MAX_HCA, IB_INVALID_PD_HANDLE, cleanup);\r
717         hobul_p = mlnx_hobul_array[hca_idx];\r
718         if (NULL == hobul_p) {\r
719                 status = IB_INVALID_PD_HANDLE;\r
720                 goto cleanup;\r
721         }\r
722         VALIDATE_INDEX(pd_idx, hobul_p->max_pd, IB_INVALID_PD_HANDLE, cleanup);\r
723         if (E_MARK_PD != hobul_p->pd_info_tbl[pd_idx].mark) {\r
724                 status =  IB_INVALID_PD_HANDLE;\r
725                 goto cleanup;\r
726         }\r
727 \r
728         if (!p_rkey || !ph_mw) {\r
729                 status = IB_INVALID_PARAMETER;\r
730                 goto cleanup;\r
731         }\r
732 \r
733         if (NULL == (mwo_p = cl_zalloc( sizeof(mlnx_mwo_t)))) {\r
734                 status = IB_INSUFFICIENT_MEMORY;\r
735                 goto cleanup; \r
736         }\r
737 \r
738         if (HH_OK != THH_hob_alloc_mw(hobul_p->hh_hndl, pd_idx, (IB_rkey_t *)&mwo_p->mw_rkey))\r
739         {\r
740                 status = IB_ERROR;\r
741                 goto cleanup;\r
742         }\r
743 \r
744         // update PD object count\r
745         cl_atomic_inc(&hobul_p->pd_info_tbl[pd_idx].count);\r
746 \r
747         mwo_p->mark    = E_MARK_MW;\r
748         mwo_p->hca_idx = hca_idx;\r
749         mwo_p->pd_idx  = pd_idx;\r
750         *p_rkey = cl_hton32( mwo_p->mw_rkey );\r
751 \r
752         *ph_mw = (ib_mw_handle_t)mwo_p;\r
753 \r
754         if( p_umv_buf && p_umv_buf->command )\r
755         {\r
756                 p_umv_buf->output_size = 0;\r
757                 p_umv_buf->status = IB_SUCCESS;\r
758         }\r
759         CL_EXIT(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
760         return IB_SUCCESS;\r
761 \r
762 cleanup:\r
763         if (mwo_p) {\r
764                 mwo_p->mark = E_MARK_INVALID;\r
765                 cl_free( mwo_p);\r
766         }\r
767         if( p_umv_buf && p_umv_buf->command )\r
768         {\r
769                 p_umv_buf->output_size = 0;\r
770                 p_umv_buf->status = status;\r
771         }\r
772         CL_TRACE(CL_DBG_ERROR, g_mlnx_dbg_lvl, ("completes with ERROR status %d\n", status));\r
773         CL_EXIT(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
774         return status;\r
775 }\r
776 \r
777 ib_api_status_t\r
778 mlnx_query_mw (\r
779         IN              const   ib_mw_handle_t                          h_mw,\r
780                 OUT                     ib_pd_handle_t                          *ph_pd,\r
781                 OUT                     net32_t* const                          p_rkey,\r
782         IN      OUT                     ci_umv_buf_t                            *p_umv_buf )\r
783 {\r
784         mlnx_mwo_t                      *mwo_p = NULL;\r
785         u_int32_t                       hca_idx;\r
786         u_int32_t                       pd_idx;\r
787         mlnx_hobul_t            *hobul_p;\r
788         ib_api_status_t         status;\r
789 \r
790 \r
791         CL_ENTER(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
792 \r
793         if( !cl_is_blockable() )\r
794                 return IB_UNSUPPORTED;\r
795 \r
796         mwo_p = (mlnx_mwo_t *)h_mw;\r
797         if (!mwo_p || mwo_p->mark != E_MARK_MW) {\r
798                 status = IB_INVALID_MW_HANDLE;\r
799                 goto cleanup;\r
800         }\r
801 \r
802         hca_idx = mwo_p->hca_idx;\r
803         pd_idx  = mwo_p->pd_idx;\r
804 \r
805         VALIDATE_INDEX(hca_idx, MLNX_MAX_HCA, IB_INVALID_MW_HANDLE, cleanup);\r
806         hobul_p = mlnx_hobul_array[hca_idx];\r
807         if (NULL == hobul_p) {\r
808                 status = IB_INVALID_MW_HANDLE;\r
809                 goto cleanup;\r
810         }\r
811         VALIDATE_INDEX(pd_idx, hobul_p->max_pd, IB_INVALID_MW_HANDLE, cleanup);\r
812         if (E_MARK_PD != hobul_p->pd_info_tbl[pd_idx].mark) {\r
813                 status =  IB_INVALID_MW_HANDLE;\r
814                 goto cleanup;\r
815         }\r
816 \r
817         if (ph_pd) *ph_pd   = (ib_pd_handle_t)PD_HNDL_FROM_PD(pd_idx);\r
818         if (p_rkey) *p_rkey = cl_hton32( mwo_p->mw_rkey );\r
819 \r
820         if( p_umv_buf && p_umv_buf->command )\r
821         {\r
822                 p_umv_buf->output_size = 0;\r
823                 p_umv_buf->status = IB_SUCCESS;\r
824         }\r
825         CL_EXIT(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
826         return IB_SUCCESS;\r
827 \r
828 cleanup:\r
829         if( p_umv_buf && p_umv_buf->command )\r
830         {\r
831                 p_umv_buf->output_size = 0;\r
832                 p_umv_buf->status = status;\r
833         }\r
834         CL_TRACE(CL_DBG_ERROR, g_mlnx_dbg_lvl, ("completes with ERROR status %d\n", status));\r
835         CL_EXIT(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
836         return status;\r
837 }\r
838 \r
839 ib_api_status_t\r
840 mlnx_destroy_mw (\r
841         IN              const   ib_mw_handle_t                          h_mw)\r
842 {\r
843         mlnx_mwo_t                      *mwo_p = NULL;\r
844         u_int32_t                       hca_idx;\r
845         u_int32_t                       pd_idx;\r
846         mlnx_hobul_t            *hobul_p;\r
847         ib_api_status_t         status;\r
848 \r
849 \r
850         CL_ENTER(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
851 \r
852         if( !cl_is_blockable() )\r
853                 return IB_UNSUPPORTED;\r
854 \r
855         mwo_p = (mlnx_mwo_t *)h_mw;\r
856         if (!mwo_p || mwo_p->mark != E_MARK_MW) {\r
857                 status = IB_INVALID_MW_HANDLE;\r
858                 goto cleanup;\r
859         }\r
860 \r
861         hca_idx = mwo_p->hca_idx;\r
862         pd_idx  = mwo_p->pd_idx;\r
863 \r
864         VALIDATE_INDEX(hca_idx, MLNX_MAX_HCA, IB_INVALID_MW_HANDLE, cleanup);\r
865         hobul_p = mlnx_hobul_array[hca_idx];\r
866         if (NULL == hobul_p) {\r
867                 status = IB_INVALID_PD_HANDLE;\r
868                 goto cleanup;\r
869         }\r
870         VALIDATE_INDEX(pd_idx, hobul_p->max_pd, IB_INVALID_MW_HANDLE, cleanup);\r
871         if (E_MARK_PD != hobul_p->pd_info_tbl[pd_idx].mark) {\r
872                 status =  IB_INVALID_PD_HANDLE;\r
873                 goto cleanup;\r
874         }\r
875 \r
876         if (HH_OK != THH_hob_free_mw(hobul_p->hh_hndl, (IB_rkey_t)mwo_p->mw_rkey))\r
877         {\r
878                 status = IB_ERROR;\r
879                 goto cleanup;\r
880         }\r
881 \r
882         // update PD object count\r
883         cl_atomic_dec(&hobul_p->pd_info_tbl[pd_idx].count);\r
884 \r
885         if (mwo_p) {\r
886                 mwo_p->mark = E_MARK_INVALID;\r
887                 cl_free( mwo_p);\r
888         }\r
889         CL_EXIT(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
890         return IB_SUCCESS;\r
891 \r
892 cleanup:\r
893         if (mwo_p) {\r
894                 mwo_p->mark = E_MARK_INVALID;\r
895                 cl_free( mwo_p);\r
896         }\r
897         CL_TRACE(CL_DBG_ERROR, g_mlnx_dbg_lvl, ("completes with ERROR status %d\n", status));\r
898         CL_EXIT(MLNX_DBG_TRACE, g_mlnx_dbg_lvl);\r
899         return status;\r
900 }\r
901 \r
902 \r
903 void\r
904 mlnx_memory_if(\r
905         IN      OUT                     ci_interface_t                          *p_interface )\r
906 {\r
907         p_interface->register_mr = mlnx_register_mr;\r
908         p_interface->register_pmr = mlnx_register_pmr;\r
909         p_interface->query_mr = mlnx_query_mr;\r
910         p_interface->modify_mr = mlnx_modify_mr;\r
911         p_interface->modify_pmr = mlnx_modify_pmr;\r
912         p_interface->register_smr = mlnx_register_smr;\r
913         p_interface->deregister_mr = mlnx_deregister_mr;\r
914 \r
915         p_interface->create_mw = mlnx_create_mw;\r
916         p_interface->query_mw = mlnx_query_mw;\r
917         p_interface->destroy_mw = mlnx_destroy_mw;\r
918 }\r
919 \r