fc5a2a321178c6c872b5f2f54885c4a59040d25b
[mirror/winof/.git] / hw / mthca / user / mlnx_ual_qp.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_qp.tmh"\r
41 #endif\r
42 \r
43 static void\r
44 __nd_modify_qp(\r
45         IN              const   ib_qp_handle_t                          h_uvp_qp,\r
46         OUT                             void**                                          pp_outbuf,\r
47         OUT                             DWORD*                                  p_size\r
48         )\r
49 {\r
50         struct ibv_qp *ibv_qp = (struct ibv_qp *)h_uvp_qp;\r
51         UVP_ENTER(UVP_DBG_QP);\r
52         *(uint32_t**)pp_outbuf = (uint32_t*)&ibv_qp->state;\r
53         *p_size = sizeof(ibv_qp->state);\r
54         UVP_EXIT(UVP_DBG_QP);\r
55 }\r
56 \r
57 static ib_qp_state_t __qp_state_to_ibal(enum ibv_qp_state state)\r
58 {\r
59         switch ( state ) {\r
60                 case IBV_QPS_RESET: return IB_QPS_RESET;\r
61                 case IBV_QPS_INIT: return IB_QPS_INIT;\r
62                 case IBV_QPS_RTR: return IB_QPS_RTR;\r
63                 case IBV_QPS_RTS: return IB_QPS_RTS;\r
64                 case IBV_QPS_SQD: return IB_QPS_SQD;\r
65                 case IBV_QPS_SQE: return IB_QPS_SQERR;\r
66                 case IBV_QPS_ERR: return IB_QPS_ERROR;\r
67                 default: return IB_QPS_TIME_WAIT;\r
68         };\r
69 }\r
70 \r
71 static uint32_t\r
72 __nd_get_qp_state(\r
73         IN              const   ib_qp_handle_t                          h_uvp_qp\r
74         )\r
75 {\r
76         struct ibv_qp *ibv_qp = (struct ibv_qp *)h_uvp_qp;\r
77         UVP_ENTER(UVP_DBG_QP);\r
78         return __qp_state_to_ibal( ibv_qp->state );\r
79         UVP_EXIT(UVP_DBG_QP);\r
80 }\r
81 \r
82 static ib_api_status_t\r
83 __pre_create_qp (\r
84         IN              const ib_pd_handle_t            h_uvp_pd,\r
85         IN              const ib_qp_create_t            *p_create_attr,\r
86         IN OUT  ci_umv_buf_t                    *p_umv_buf,\r
87            OUT  ib_qp_handle_t                          *ph_uvp_qp)\r
88 {\r
89         int err;\r
90         struct ibv_qp *ibv_qp;\r
91         struct ibv_qp_init_attr attr;\r
92         struct ibv_create_qp *p_create_qp;\r
93         ib_api_status_t status = IB_SUCCESS;\r
94         size_t size = max( sizeof(struct ibv_create_qp), sizeof(struct ibv_create_qp_resp) );\r
95         struct ibv_pd *ibv_pd = h_uvp_pd->ibv_pd;\r
96 \r
97         UNREFERENCED_PARAMETER(ph_uvp_qp);\r
98                 \r
99         UVP_ENTER(UVP_DBG_QP);\r
100 \r
101         CL_ASSERT(p_umv_buf);\r
102 \r
103         if( !p_umv_buf->p_inout_buf )\r
104         {\r
105                 p_umv_buf->p_inout_buf = cl_zalloc( size );\r
106                 if( !p_umv_buf->p_inout_buf )\r
107                 {\r
108                         status = IB_INSUFFICIENT_MEMORY;\r
109                         goto err_memory;\r
110                 }\r
111         }\r
112         p_umv_buf->input_size = sizeof(struct ibv_create_qp);\r
113         p_umv_buf->output_size = sizeof(struct ibv_create_qp_resp);\r
114         p_umv_buf->command = TRUE;\r
115 \r
116         /* convert attributes */\r
117         attr.send_cq                            = (struct ibv_cq *)p_create_attr->h_sq_cq;\r
118         attr.recv_cq                            = (struct ibv_cq *)p_create_attr->h_rq_cq;\r
119         attr.srq                                        = (struct ibv_srq*)p_create_attr->h_srq;\r
120         attr.cap.max_send_wr            = p_create_attr->sq_depth;\r
121         attr.cap.max_recv_wr            = p_create_attr->rq_depth;\r
122         attr.cap.max_send_sge           = p_create_attr->sq_sge;\r
123         attr.cap.max_recv_sge           = p_create_attr->rq_sge;\r
124         attr.cap.max_inline_data        = p_create_attr->sq_max_inline;\r
125         attr.qp_type                                                    = p_create_attr->qp_type;\r
126         attr.sq_sig_all                                         = p_create_attr->sq_signaled;\r
127         \r
128         /* allocate ibv_qp */\r
129         p_create_qp = (struct ibv_create_qp *)p_umv_buf->p_inout_buf;\r
130         ibv_qp = ibv_pd->context->ops.create_qp_pre(ibv_pd, &attr, p_create_qp);\r
131         if (IS_ERR(ibv_qp)) {\r
132                 err = PTR_ERR(ibv_qp);\r
133                 UVP_PRINT(TRACE_LEVEL_ERROR ,UVP_DBG_QP ,("mthca_create_qp_pre failed (%d)\n", err));\r
134                 if(err == -ENOMEM && (attr.cap.max_send_sge == 0 ||attr.cap.max_recv_sge == 0|| \r
135                         attr.cap.max_send_wr == 0 || attr.cap.max_recv_wr == 0))\r
136                         status = IB_INVALID_SETTING;\r
137                 else\r
138                         status = errno_to_iberr(err);\r
139                 goto err_alloc_qp;\r
140         }\r
141 \r
142         goto end;\r
143                 \r
144 err_alloc_qp:\r
145         cl_free(p_umv_buf->p_inout_buf);\r
146 err_memory:\r
147 end:\r
148                 UVP_EXIT(UVP_DBG_QP);\r
149                 return status;\r
150 }\r
151 \r
152 static ib_api_status_t\r
153 __post_create_qp (\r
154         IN              const ib_pd_handle_t                            h_uvp_pd,\r
155         IN                              ib_api_status_t                         ioctl_status,\r
156         IN      OUT                     ib_qp_handle_t                          *ph_uvp_qp,\r
157         IN                              ci_umv_buf_t                            *p_umv_buf )\r
158 {\r
159         int err;\r
160         struct ibv_qp *ibv_qp;\r
161         struct ibv_create_qp_resp *p_resp;\r
162         struct ibv_create_qp *p_create_qp;\r
163         ib_api_status_t status = IB_SUCCESS;\r
164         struct ibv_pd *ibv_pd = h_uvp_pd->ibv_pd;\r
165 \r
166         UVP_ENTER(UVP_DBG_QP);\r
167 \r
168 \r
169         CL_ASSERT(p_umv_buf);\r
170         p_resp = (struct ibv_create_qp_resp *)p_umv_buf->p_inout_buf;\r
171 \r
172         if (IB_SUCCESS == ioctl_status) {\r
173 \r
174                 /* allocate ibv_qp */\r
175                 ibv_qp = ibv_pd->context->ops.create_qp_post(ibv_pd, p_resp);\r
176                 if (IS_ERR(ibv_qp)) {\r
177                         err = PTR_ERR(ibv_qp);\r
178                         UVP_PRINT(TRACE_LEVEL_ERROR ,UVP_DBG_QP , ("mthca_create_qp_post failed (%d)\n", err));\r
179                         status = errno_to_iberr(err);\r
180                         goto err_create_cq;\r
181                 }\r
182 \r
183                 *ph_uvp_qp = (ib_qp_handle_t)ibv_qp;\r
184         }\r
185         goto end;\r
186         \r
187         ibv_pd->context->ops.destroy_qp(ibv_qp);\r
188 err_create_cq:\r
189 end:    \r
190         if (p_resp)\r
191                 cl_free( p_resp );\r
192         UVP_EXIT(UVP_DBG_QP);\r
193         return status;\r
194 }\r
195 \r
196 static ib_api_status_t\r
197 __pre_modify_qp (\r
198         IN              const ib_qp_handle_t    h_uvp_qp,\r
199         IN              const ib_qp_mod_t               *p_modify_attr,\r
200         IN OUT  ci_umv_buf_t                    *p_umv_buf)\r
201 {\r
202         ib_api_status_t status = IB_SUCCESS;\r
203         UNREFERENCED_PARAMETER(h_uvp_qp);\r
204         UNREFERENCED_PARAMETER(p_modify_attr);\r
205 \r
206         UVP_ENTER(UVP_DBG_SHIM);\r
207 \r
208         CL_ASSERT(p_umv_buf);\r
209 \r
210         if( !p_umv_buf->p_inout_buf )\r
211         {\r
212                 p_umv_buf->p_inout_buf = cl_zalloc( sizeof(struct ibv_modify_qp_resp) );\r
213                 if( !p_umv_buf->p_inout_buf )\r
214                 {\r
215                         status = IB_INSUFFICIENT_MEMORY;\r
216                         goto err_memory;\r
217                 }\r
218         }\r
219         p_umv_buf->input_size = 0;\r
220         p_umv_buf->output_size = sizeof(struct ibv_modify_qp_resp);\r
221         p_umv_buf->command = TRUE;\r
222         \r
223 err_memory:\r
224         UVP_EXIT(UVP_DBG_SHIM);\r
225         return status;\r
226 }\r
227 \r
228 \r
229 static void\r
230 __post_modify_qp (\r
231         IN              const ib_qp_handle_t    h_uvp_qp,\r
232         IN              ib_api_status_t                 ioctl_status,\r
233         IN OUT  ci_umv_buf_t                    *p_umv_buf)\r
234 {\r
235         int err;\r
236         ib_api_status_t status;\r
237         struct ibv_modify_qp_resp *p_resp; \r
238         struct ibv_qp_attr attr;\r
239         struct ibv_qp *ibv_qp = (struct ibv_qp *)h_uvp_qp;\r
240 \r
241         UVP_ENTER(UVP_DBG_SHIM);\r
242         CL_ASSERT(p_umv_buf);\r
243 \r
244         p_resp = (struct ibv_modify_qp_resp *)p_umv_buf->p_inout_buf;\r
245 \r
246         if (IB_SUCCESS == ioctl_status) \r
247         {\r
248                 memset( &attr, 0, sizeof(attr));\r
249                 attr.qp_state = p_resp->qp_state;\r
250                 if (ibv_qp) {\r
251                         err = ibv_qp->context->ops.modify_qp(   ibv_qp,\r
252                                                                                                         &attr, p_resp->attr_mask);\r
253                         if (err) {\r
254                                 UVP_PRINT(TRACE_LEVEL_ERROR ,UVP_DBG_SHIM , ("mthca_modify_qp failed (%d)\n", err));\r
255                                 status = errno_to_iberr(err);\r
256                                 goto err_modify_qp;\r
257                         }\r
258                 }\r
259                 UVP_PRINT(TRACE_LEVEL_INFORMATION ,UVP_DBG_SHIM ,\r
260                         ("Committed to modify QP to state %d\n", p_resp->qp_state));\r
261         }\r
262 \r
263 \r
264 err_modify_qp:\r
265         if (p_resp)\r
266                 cl_free (p_resp);\r
267         UVP_EXIT(UVP_DBG_SHIM);\r
268         return;\r
269         }\r
270 \r
271 \r
272 static ib_api_status_t\r
273 __pre_query_qp (\r
274         IN              ib_qp_handle_t                          h_uvp_qp,\r
275         IN OUT  ci_umv_buf_t                            *p_umv_buf)\r
276 {\r
277         UNREFERENCED_PARAMETER(h_uvp_qp);\r
278         UVP_ENTER(UVP_DBG_SHIM);\r
279         p_umv_buf->input_size = p_umv_buf->output_size = 0;\r
280         p_umv_buf->command = FALSE;\r
281         p_umv_buf->status = IB_SUCCESS;\r
282         UVP_EXIT(UVP_DBG_SHIM);\r
283         return IB_SUCCESS;\r
284 }\r
285 \r
286 \r
287 static void\r
288 __post_query_qp (\r
289         IN                              ib_qp_handle_t                          h_uvp_qp,\r
290         IN                              ib_api_status_t                         ioctl_status,\r
291         IN      OUT                     ib_qp_attr_t                            *p_query_attr,\r
292         IN      OUT                     ci_umv_buf_t                            *p_umv_buf)\r
293 {\r
294         struct mthca_qp *p_mthca_qp = (struct mthca_qp *)h_uvp_qp;\r
295         UVP_ENTER(UVP_DBG_SHIM);\r
296 \r
297         UNREFERENCED_PARAMETER(p_umv_buf);\r
298         if(IB_SUCCESS == ioctl_status)\r
299         {\r
300                 p_query_attr->sq_max_inline = p_mthca_qp->max_inline_data;\r
301                 p_query_attr->sq_sge = p_mthca_qp->sq.max_gs;\r
302                 p_query_attr->sq_depth = p_mthca_qp->sq.max;\r
303                 p_query_attr->rq_sge = p_mthca_qp->rq.max_gs;\r
304                 p_query_attr->rq_depth = p_mthca_qp->rq.max;\r
305         }\r
306         UVP_EXIT(UVP_DBG_SHIM);\r
307 }\r
308 \r
309 \r
310 static ib_api_status_t\r
311 __pre_destroy_qp (\r
312     IN          const ib_qp_handle_t            h_uvp_qp)\r
313 {\r
314         int err;\r
315 \r
316 \r
317         UVP_ENTER(UVP_DBG_SHIM);\r
318 \r
319         mthca_destroy_qp_pre((struct ibv_qp*)h_uvp_qp);\r
320 \r
321         UVP_EXIT(UVP_DBG_SHIM);\r
322         return IB_SUCCESS;\r
323 }\r
324 \r
325 static void\r
326 __post_destroy_qp (\r
327         IN              const ib_qp_handle_t    h_uvp_qp,\r
328     IN          ib_api_status_t                 ioctl_status)\r
329 {\r
330         int err;\r
331 \r
332         UVP_ENTER(UVP_DBG_SHIM);\r
333 \r
334         CL_ASSERT(h_uvp_qp);\r
335 \r
336         mthca_destroy_qp_post((struct ibv_qp*)h_uvp_qp, (int)ioctl_status);\r
337         if (ioctl_status != IB_SUCCESS) \r
338                 UVP_PRINT(TRACE_LEVEL_ERROR ,UVP_DBG_SHIM , ("mthca_destroy_qp_post failed (%d)\n", ioctl_status));\r
339 \r
340         UVP_EXIT(UVP_DBG_SHIM);\r
341         return;\r
342 }\r
343 \r
344 \r
345 void\r
346 mlnx_get_qp_interface (\r
347     IN OUT      uvp_interface_t         *p_uvp )\r
348 {\r
349     UVP_ENTER(UVP_DBG_SHIM);\r
350 \r
351     CL_ASSERT(p_uvp);\r
352 \r
353     /*\r
354      * QP Management Verbs\r
355      */\r
356     p_uvp->pre_create_qp   = __pre_create_qp;\r
357     p_uvp->post_create_qp  = __post_create_qp;\r
358 \r
359     // !!! none for create_spl_qp, UAL will return error !!!\r
360 \r
361     p_uvp->pre_modify_qp   = __pre_modify_qp;\r
362     p_uvp->post_modify_qp  = __post_modify_qp;\r
363     p_uvp->pre_query_qp    = NULL;\r
364     p_uvp->post_query_qp   = __post_query_qp;\r
365     p_uvp->pre_destroy_qp  = __pre_destroy_qp;\r
366     p_uvp->post_destroy_qp = __post_destroy_qp;\r
367     p_uvp->nd_modify_qp   = __nd_modify_qp;\r
368     p_uvp->nd_get_qp_state = __nd_get_qp_state;\r
369 \r
370     UVP_EXIT(UVP_DBG_SHIM);\r
371 }\r
372 \r
373 \r
374 \r