mlx4: fix status checkmlx4: fix status check
[mirror/winof/.git] / hw / mlx4 / kernel / hca / vp.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: hca_verbs.c 2073 2007-11-13 11:38:40Z leonid $\r
32  */\r
33 \r
34 #include "precomp.h"\r
35 \r
36 #if defined(EVENT_TRACING)\r
37 #ifdef offsetof\r
38 #undef offsetof\r
39 #endif\r
40 #include "vp.tmh"\r
41 #endif\r
42 \r
43 static ib_api_status_t\r
44 mlnx_um_open(\r
45         IN              const   ib_ca_handle_t                          h_ca,\r
46         IN      OUT                     ci_umv_buf_t* const                     p_umv_buf,\r
47                 OUT                     ib_ca_handle_t* const           ph_um_ca )\r
48 {\r
49         ib_api_status_t         status;\r
50         mlnx_hca_t                      *p_hca = (mlnx_hca_t *)h_ca;\r
51         PFDO_DEVICE_DATA p_fdo = hca2fdo(p_hca);\r
52         struct ib_device *p_ibdev = hca2ibdev(p_hca);\r
53         struct ib_ucontext *p_uctx;\r
54         struct ibv_get_context_resp *p_uresp;\r
55 \r
56         HCA_ENTER(HCA_DBG_SHIM);\r
57 \r
58         // sanity check\r
59         ASSERT( p_umv_buf );\r
60         if( !p_umv_buf->command )\r
61         { // no User Verb Provider\r
62                 p_uctx = cl_zalloc( sizeof(struct ib_ucontext) );\r
63                 if( !p_uctx )\r
64                 {\r
65                         status = IB_INSUFFICIENT_MEMORY;\r
66                         goto err_alloc_ucontext;\r
67                 }\r
68                 /* Copy the dev info. */\r
69                 p_uctx->device = p_ibdev;\r
70                 p_umv_buf->output_size = 0;\r
71                 status = IB_SUCCESS;\r
72                 goto done;\r
73         }\r
74 \r
75         // sanity check\r
76         if ( p_umv_buf->output_size < sizeof(struct ibv_get_context_resp) ||\r
77                 !p_umv_buf->p_inout_buf) {\r
78                 status = IB_INVALID_PARAMETER;\r
79                 goto err_inval_params;\r
80         }\r
81 \r
82         status = ibv_um_open( p_ibdev, p_umv_buf, &p_uctx );\r
83         if (status != IB_SUCCESS) {\r
84                 goto end;\r
85         }\r
86         \r
87         // fill more parameters for user (sanity checks are in mthca_alloc_ucontext) \r
88         p_uresp = (struct ibv_get_context_resp *)(ULONG_PTR)p_umv_buf->p_inout_buf;\r
89         p_uresp->vend_id                 = (uint32_t)p_fdo->bus_ib_ifc.pdev->ven_id;\r
90         p_uresp->dev_id                  = (uint16_t)p_fdo->bus_ib_ifc.pdev->dev_id;\r
91         p_uresp->max_qp_wr               = hca2mdev(p_hca)->caps.max_wqes;\r
92         p_uresp->max_cqe                 = hca2mdev(p_hca)->caps.max_cqes;\r
93         p_uresp->max_sge                 = min( hca2mdev(p_hca)->caps.max_sq_sg,\r
94                 hca2mdev(p_hca)->caps.max_rq_sg );\r
95 \r
96 done:\r
97         // fill the rest of ib_ucontext_ex fields \r
98         atomic_set(&p_uctx->x.usecnt, 0);\r
99         p_uctx->x.va = p_uctx->x.p_mdl = NULL;\r
100         p_uctx->x.fw_if_open = FALSE;\r
101         mutex_init( &p_uctx->x.mutex );\r
102 \r
103         // chain user context to the device\r
104         spin_lock( &p_fdo->uctx_lock );\r
105         cl_qlist_insert_tail( &p_fdo->uctx_list, &p_uctx->x.list_item );\r
106         cl_atomic_inc(&p_fdo->usecnt);\r
107         spin_unlock( &p_fdo->uctx_lock );\r
108         \r
109         // return the result\r
110         if (ph_um_ca) *ph_um_ca = (ib_ca_handle_t)p_uctx;\r
111 \r
112         status = IB_SUCCESS;\r
113         goto end;\r
114 \r
115 err_inval_params:\r
116 err_alloc_ucontext:\r
117 end:\r
118         if (p_umv_buf && p_umv_buf->command) \r
119                 p_umv_buf->status = status;\r
120         if (status != IB_SUCCESS) \r
121         {\r
122                 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_SHIM,\r
123                         ("completes with ERROR status %x\n", status));\r
124         }\r
125         HCA_EXIT(HCA_DBG_SHIM);\r
126         return status;\r
127 }\r
128 \r
129 \r
130 static void\r
131 mlnx_um_close(\r
132         IN                              ib_ca_handle_t                          h_ca,\r
133         IN                              ib_ca_handle_t                          h_um_ca )\r
134 {\r
135         struct ib_ucontext *p_uctx = (struct ib_ucontext *)h_um_ca;\r
136         PFDO_DEVICE_DATA p_fdo = p_uctx->device->x.p_fdo;\r
137 \r
138         UNUSED_PARAM(h_ca);\r
139         \r
140         if ( !hca_is_livefish(p_fdo))\r
141                 unmap_crspace_for_all(p_uctx);\r
142         spin_lock( &p_fdo->uctx_lock );\r
143         cl_qlist_remove_item( &p_fdo->uctx_list, &p_uctx->x.list_item );\r
144         cl_atomic_dec(&p_fdo->usecnt);\r
145         spin_unlock( &p_fdo->uctx_lock );\r
146         if( !p_uctx->x.uar.kva)\r
147                 cl_free( h_um_ca );             // no User Verb Provider\r
148         else \r
149                 ibv_um_close(p_uctx);\r
150 #if 0\r
151         // TODO: replace where pa_cash.c is found\r
152         pa_cash_print();\r
153 #endif\r
154         return;\r
155 }\r
156 \r
157 \r
158 ib_api_status_t\r
159 mlnx_local_mad (\r
160         IN              const   ib_ca_handle_t                          h_ca,\r
161         IN              const   uint8_t                                         port_num,\r
162         IN              const   ib_av_attr_t*                                   p_av_attr,\r
163         IN              const   ib_mad_t                                        *p_mad_in,\r
164         OUT             ib_mad_t                                        *p_mad_out )\r
165 {\r
166         int err;\r
167         ib_api_status_t         status = IB_SUCCESS;\r
168         mlnx_hca_t                      *p_hca = (mlnx_hca_t *)h_ca;\r
169         PFDO_DEVICE_DATA p_fdo = hca2fdo(p_hca);\r
170         struct ib_device *p_ibdev = p_fdo->bus_ib_ifc.p_ibdev;\r
171         //TODO: do we need use flags (IB_MAD_IGNORE_MKEY, IB_MAD_IGNORE_BKEY) ?\r
172         int mad_flags = 0;  \r
173         //TODO: do we need use grh ?\r
174         struct ib_grh *p_grh = NULL;\r
175         ib_wc_t *p_wc = NULL;\r
176 \r
177         HCA_ENTER(HCA_DBG_MAD);\r
178 \r
179         // sanity checks\r
180         if (port_num > 2) {\r
181                 status = IB_INVALID_PARAMETER;\r
182                 goto err_port_num;\r
183         }\r
184 \r
185         if (p_av_attr){\r
186                 p_wc = cl_zalloc(sizeof(ib_wc_t));\r
187                 if(!p_wc){\r
188                         status =  IB_INSUFFICIENT_MEMORY ;\r
189                         goto err_wc_alloc;\r
190                 }\r
191                 //Copy part of the attributes need to fill the mad extended fields in mellanox devices\r
192                 p_wc->recv.ud.remote_lid = p_av_attr->dlid;\r
193                 p_wc->recv.ud.remote_sl  = p_av_attr->sl;\r
194                 p_wc->recv.ud.path_bits  = p_av_attr->path_bits;\r
195                 p_wc->recv.ud.recv_opt = p_av_attr->grh_valid ? IB_RECV_OPT_GRH_VALID : 0;\r
196 \r
197                 if(p_wc->recv.ud.recv_opt & IB_RECV_OPT_GRH_VALID){\r
198                         p_grh = cl_zalloc(sizeof(struct _ib_grh));\r
199                         if(!p_grh){\r
200                                 status =  IB_INSUFFICIENT_MEMORY ;\r
201                                 goto err_grh_alloc;\r
202                         }\r
203                         p_grh->version_tclass_flow      = p_av_attr->grh.ver_class_flow;\r
204                         p_grh->hop_limit                        = p_av_attr->grh.hop_limit;\r
205                         cl_memcpy( &p_grh->sgid, &p_av_attr->grh.src_gid, sizeof(p_grh->sgid) );\r
206                         cl_memcpy( &p_grh->dgid, &p_av_attr->grh.dest_gid, sizeof(p_grh->dgid) );\r
207                         // TODO: no direct analogue in IBAL (seems like it is from rmpp)\r
208                         p_grh->paylen                           = 0;\r
209                         p_grh->next_hdr                         = 0;\r
210                 }\r
211                         \r
212 \r
213         }\r
214 \r
215         HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_MAD, \r
216                 ("MAD: Class %02x, Method %02x, Attr %02x, HopPtr %d, HopCnt %d, \n",\r
217                 (uint32_t)((ib_smp_t *)p_mad_in)->mgmt_class, \r
218                 (uint32_t)((ib_smp_t *)p_mad_in)->method, \r
219                 (uint32_t)((ib_smp_t *)p_mad_in)->attr_id, \r
220                 (uint32_t)((ib_smp_t *)p_mad_in)->hop_ptr,\r
221                 (uint32_t)((ib_smp_t *)p_mad_in)->hop_count));\r
222 \r
223         // process mad\r
224         err = p_ibdev->process_mad( p_ibdev, mad_flags, (uint8_t)port_num, \r
225                 p_wc, p_grh, (struct ib_mad*)p_mad_in, (struct ib_mad*)p_mad_out);\r
226         if (!err) {\r
227                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_MAD, \r
228                         ("MAD failed:\n\tClass 0x%x\n\tMethod 0x%x\n\tAttr 0x%x",\r
229                         p_mad_in->mgmt_class, p_mad_in->method, p_mad_in->attr_id ));\r
230                 status = IB_ERROR;\r
231                 goto err_process_mad;\r
232         }\r
233         \r
234         if( (p_mad_in->mgmt_class == IB_MCLASS_SUBN_DIR ||\r
235                 p_mad_in->mgmt_class == IB_MCLASS_SUBN_LID) &&\r
236                 p_mad_in->attr_id == IB_MAD_ATTR_PORT_INFO )\r
237         {\r
238                 ib_port_info_t  *p_pi_in, *p_pi_out;\r
239 \r
240                 if( p_mad_in->mgmt_class == IB_MCLASS_SUBN_DIR )\r
241                 {\r
242                         p_pi_in = (ib_port_info_t*)\r
243                                 ib_smp_get_payload_ptr( (ib_smp_t*)p_mad_in );\r
244                         p_pi_out = (ib_port_info_t*)\r
245                                 ib_smp_get_payload_ptr( (ib_smp_t*)p_mad_out );\r
246                 }\r
247                 else\r
248                 {\r
249                         p_pi_in = (ib_port_info_t*)(p_mad_in + 1);\r
250                         p_pi_out = (ib_port_info_t*)(p_mad_out + 1);\r
251                 }\r
252 \r
253                 /* Work around FW bug 33958 */\r
254                 p_pi_out->subnet_timeout &= 0x7F;\r
255                 if( p_mad_in->method == IB_MAD_METHOD_SET )\r
256                         p_pi_out->subnet_timeout |= (p_pi_in->subnet_timeout & 0x80);\r
257         }\r
258 \r
259         /* Modify direction for Direct MAD */\r
260         if ( p_mad_in->mgmt_class == IB_MCLASS_SUBN_DIR )\r
261                 p_mad_out->status |= IB_SMP_DIRECTION;\r
262 \r
263 \r
264 err_process_mad:\r
265         if(p_grh)\r
266                 cl_free(p_grh);\r
267 err_grh_alloc:\r
268         if(p_wc)\r
269                 cl_free(p_wc);\r
270 err_wc_alloc:\r
271 err_port_num:   \r
272         if (status != IB_SUCCESS)\r
273         {\r
274                 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_MAD,\r
275                         ("completes with ERROR status %x\n", status));\r
276         }\r
277         HCA_EXIT(HCA_DBG_MAD);\r
278         return status;\r
279 }\r
280         \r
281 \r
282 void\r
283 setup_ci_interface(\r
284         IN              const   ib_net64_t                                      ca_guid,\r
285         IN              const   int                                                     is_livefish,\r
286         IN      OUT                     ci_interface_t                          *p_interface )\r
287 {\r
288         cl_memclr(p_interface, sizeof(*p_interface));\r
289 \r
290         /* Guid of the CA. */\r
291         p_interface->guid = ca_guid;\r
292 \r
293         /* Version of this interface. */\r
294         p_interface->version = VERBS_VERSION;\r
295 \r
296         /* UVP name */\r
297         cl_memcpy( p_interface->libname, mlnx_uvp_lib_name, MAX_LIB_NAME);\r
298 \r
299         HCA_PRINT(TRACE_LEVEL_VERBOSE  , HCA_DBG_SHIM  ,("UVP filename %s\n", p_interface->libname));\r
300 \r
301         /* The real interface. */\r
302         mlnx_pd_if(p_interface);\r
303         p_interface->um_open_ca = mlnx_um_open;\r
304         p_interface->um_close_ca = mlnx_um_close;\r
305         p_interface->vendor_call = fw_access_ctrl;\r
306 \r
307         if (is_livefish) {\r
308                 mlnx_ca_if_livefish(p_interface);\r
309                 mlnx_mr_if_livefish(p_interface);\r
310         }\r
311         else {  \r
312                 mlnx_ca_if(p_interface);\r
313                 mlnx_av_if(p_interface);\r
314                 mlnx_srq_if(p_interface);\r
315                 mlnx_qp_if(p_interface);\r
316                 mlnx_cq_if(p_interface);\r
317                 mlnx_mr_if(p_interface);\r
318                 mlnx_direct_if(p_interface);\r
319                 mlnx_mcast_if(p_interface);\r
320                 p_interface->local_mad = mlnx_local_mad;\r
321         }\r
322 \r
323         return;\r
324 }\r
325 \r
326 \r