[IBAL, HW] Remove pointers from ci_umv_buf_t.
[mirror/winof/.git] / hw / mlx4 / kernel / hca / qp.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  * Copyright (c) 1996-2003 Intel Corporation. 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: al.c 1611 2006-08-20 14:48:55Z sleybo $\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 "qp.tmh"\r
41 #endif\r
42 \r
43 \r
44 ib_api_status_t\r
45 mlnx_query_qp (\r
46         IN              const   ib_qp_handle_t                          h_qp,\r
47                 OUT                     ib_qp_attr_t                            *p_qp_attr,\r
48         IN      OUT                     ci_umv_buf_t                            *p_umv_buf )\r
49 {\r
50         ib_api_status_t         status;\r
51         struct ib_qp *p_ib_qp = (struct ib_qp *)h_qp;\r
52         struct ib_qp_attr qp_attr;\r
53         struct ib_qp_init_attr qp_init_attr;\r
54         int qp_attr_mask = 0;\r
55         int err;\r
56 \r
57         UNREFERENCED_PARAMETER(p_umv_buf);\r
58         \r
59         HCA_ENTER( HCA_DBG_QP);\r
60 \r
61         // sanity checks\r
62         if (!p_qp_attr) {\r
63                 status =  IB_INVALID_PARAMETER;\r
64                 goto err_parm;\r
65         }\r
66 \r
67         // convert structures\r
68         memset( &qp_attr, 0, sizeof(struct ib_qp_attr) );\r
69         err = p_ib_qp->device->query_qp( p_ib_qp, &qp_attr, \r
70                 qp_attr_mask, &qp_init_attr);\r
71         if (err){\r
72                 status = errno_to_iberr(err);\r
73                 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_PD,\r
74                         ("ib_query_qp failed (%#x)\n", status));\r
75                 goto err_query_qp;\r
76         }\r
77 \r
78         status = from_qp_attr( p_ib_qp, &qp_attr, p_qp_attr );\r
79 \r
80 err_query_qp:\r
81 err_parm:\r
82         HCA_EXIT(HCA_DBG_QP);\r
83         return status;\r
84 }\r
85 \r
86 static ib_api_status_t\r
87 __create_qp (\r
88         IN              const   ib_pd_handle_t                          h_pd,\r
89         IN              const   uint8_t                                         port_num,\r
90         IN              const   void                                            *qp_uctx,\r
91         IN              const   ib_qp_create_t                          *p_create_attr,\r
92                 OUT                     ib_qp_attr_t                            *p_qp_attr,\r
93                 OUT                     ib_qp_handle_t                          *ph_qp,\r
94         IN      OUT                     ci_umv_buf_t                            *p_umv_buf )\r
95 {\r
96         int err;\r
97         ib_api_status_t         status;\r
98         struct ib_qp * p_ib_qp;\r
99         struct ib_qp_init_attr qp_init_attr;\r
100         struct ib_ucontext *p_uctx = NULL;\r
101         struct ib_pd *p_ib_pd = (struct ib_pd *)h_pd;\r
102         struct ib_device *p_ib_dev = p_ib_pd->device;\r
103         mlnx_hca_t *p_hca = ibdev2hca(p_ib_dev);\r
104         struct ibv_create_qp *p_req = NULL;\r
105         \r
106         HCA_ENTER(HCA_DBG_QP);\r
107 \r
108         if( p_umv_buf && p_umv_buf->command ) {\r
109                 // sanity checks \r
110                 if (p_umv_buf->input_size < sizeof(struct ibv_create_qp) ||\r
111                         p_umv_buf->output_size < sizeof(struct ibv_create_qp_resp) ||\r
112                         !p_umv_buf->p_inout_buf) {\r
113                         status = IB_INVALID_PARAMETER;\r
114                         goto err_inval_params;\r
115                 }\r
116                 p_req = (struct ibv_create_qp*)(ULONG_PTR)p_umv_buf->p_inout_buf;\r
117                 p_uctx = p_ib_pd->p_uctx;\r
118         }\r
119 \r
120         // prepare the parameters\r
121         RtlZeroMemory(&qp_init_attr, sizeof(qp_init_attr));\r
122         qp_init_attr.event_handler = qp_event_handler;\r
123         qp_init_attr.qp_context = p_hca;\r
124         qp_init_attr.send_cq = (struct ib_cq *)p_create_attr->h_sq_cq;\r
125         qp_init_attr.recv_cq = (struct ib_cq *)p_create_attr->h_rq_cq;\r
126         qp_init_attr.srq = (struct ib_srq *)p_create_attr->h_srq;\r
127         if( p_umv_buf && p_umv_buf->command ) {\r
128                 qp_init_attr.cap.max_recv_sge = p_req->max_recv_sge;\r
129                 qp_init_attr.cap.max_send_sge = p_req->max_send_sge;\r
130                 qp_init_attr.cap.max_recv_wr = p_req->max_recv_wr;\r
131                 qp_init_attr.cap.max_send_wr = p_req->max_send_wr;\r
132                 qp_init_attr.cap.max_inline_data = p_req->max_inline_data;\r
133         }\r
134         else {\r
135                 qp_init_attr.cap.max_recv_sge = p_create_attr->rq_sge;\r
136                 qp_init_attr.cap.max_send_sge = p_create_attr->sq_sge;\r
137                 qp_init_attr.cap.max_recv_wr = p_create_attr->rq_depth;\r
138                 qp_init_attr.cap.max_send_wr = p_create_attr->sq_depth;\r
139                 qp_init_attr.cap.max_inline_data = 0;   /* absent in IBAL */\r
140         }\r
141         qp_init_attr.sq_sig_type = (p_create_attr->sq_signaled) ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;\r
142         qp_init_attr.qp_type = to_qp_type(p_create_attr->qp_type);\r
143         qp_init_attr.port_num = port_num;\r
144 \r
145         // create qp            \r
146         p_ib_qp = ibv_create_qp( p_ib_pd, &qp_init_attr, p_uctx, p_umv_buf );\r
147         if (IS_ERR(p_ib_qp)) {\r
148                 err = PTR_ERR(p_ib_qp);\r
149                 HCA_PRINT(TRACE_LEVEL_ERROR  , HCA_DBG_QP,\r
150                         ("ibv_create_qp failed (%d)\n", err));\r
151                 status = errno_to_iberr(err);\r
152                 goto err_create_qp;\r
153         }\r
154 \r
155         // fill the object\r
156         p_ib_qp->x.ctx = (void*)qp_uctx;\r
157 \r
158         // Query QP to obtain requested attributes\r
159         if (p_qp_attr) {\r
160                 status = mlnx_query_qp((ib_qp_handle_t)p_ib_qp, p_qp_attr, p_umv_buf);\r
161                 if (status != IB_SUCCESS)\r
162                         goto err_query_qp;\r
163         }\r
164         \r
165         // return the results\r
166         if (ph_qp) *ph_qp = (ib_qp_handle_t)p_ib_qp;\r
167 \r
168         status = IB_SUCCESS;\r
169         goto end;\r
170 \r
171 err_query_qp:\r
172         ib_destroy_qp( p_ib_qp );\r
173 err_create_qp:\r
174 err_inval_params:\r
175 end:\r
176         if (p_umv_buf && p_umv_buf->command) \r
177                 p_umv_buf->status = status;\r
178         if (status != IB_SUCCESS)\r
179                 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_QP,\r
180                         ("completes with ERROR status %x\n", status));\r
181         HCA_EXIT(HCA_DBG_QP);\r
182         return status;\r
183 }\r
184 \r
185 ib_api_status_t\r
186 mlnx_create_spl_qp (\r
187         IN              const   ib_pd_handle_t                          h_pd,\r
188         IN              const   uint8_t                                         port_num,\r
189         IN              const   void                                            *qp_uctx,\r
190         IN              const   ib_qp_create_t                          *p_create_attr,\r
191                 OUT                     ib_qp_attr_t                            *p_qp_attr,\r
192                 OUT                     ib_qp_handle_t                          *ph_qp )\r
193 {\r
194         ib_api_status_t         status;\r
195 \r
196         HCA_ENTER(HCA_DBG_SHIM);\r
197 \r
198         status = __create_qp( h_pd, port_num,\r
199                 qp_uctx, p_create_attr, p_qp_attr, ph_qp, NULL );\r
200                 \r
201         if (status != IB_SUCCESS)\r
202                 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_QP,\r
203                         ("completes with ERROR status %x\n", status));\r
204         HCA_EXIT(HCA_DBG_QP);\r
205         return status;\r
206 }\r
207 \r
208 ib_api_status_t\r
209 mlnx_create_qp (\r
210         IN              const   ib_pd_handle_t                          h_pd,\r
211         IN              const   void                                            *qp_uctx,\r
212         IN              const   ib_qp_create_t                          *p_create_attr,\r
213                 OUT                     ib_qp_attr_t                            *p_qp_attr,\r
214                 OUT                     ib_qp_handle_t                          *ph_qp,\r
215         IN      OUT                     ci_umv_buf_t                            *p_umv_buf )\r
216 {\r
217         ib_api_status_t         status;\r
218 \r
219         //NB: algorithm of mthca_alloc_sqp() requires port_num\r
220         // PRM states, that special pares are created in couples, so\r
221         // looks like we can put here port_num = 1 always\r
222         uint8_t port_num = 1;\r
223 \r
224         HCA_ENTER(HCA_DBG_QP);\r
225 \r
226         status = __create_qp( h_pd, port_num,\r
227                 qp_uctx, p_create_attr, p_qp_attr, ph_qp, p_umv_buf );\r
228                 \r
229         if (status != IB_SUCCESS)\r
230                 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_QP,\r
231                         ("completes with ERROR status %x\n", status));\r
232         HCA_EXIT(HCA_DBG_QP);\r
233         return status;\r
234 }\r
235 \r
236 ib_api_status_t\r
237 mlnx_modify_qp (\r
238         IN              const   ib_qp_handle_t                          h_qp,\r
239         IN              const   ib_qp_mod_t                                     *p_modify_attr,\r
240                 OUT                     ib_qp_attr_t                            *p_qp_attr OPTIONAL,\r
241         IN      OUT                     ci_umv_buf_t                            *p_umv_buf OPTIONAL )\r
242 {\r
243         int err;\r
244         ib_api_status_t         status;\r
245         struct ib_qp_attr qp_attr;\r
246         int qp_attr_mask;\r
247         struct ib_qp *p_ib_qp = (struct ib_qp *)h_qp;\r
248 \r
249         HCA_ENTER(HCA_DBG_QP);\r
250 \r
251         // sanity checks\r
252         if( p_umv_buf && p_umv_buf->command ) {\r
253                 // sanity checks \r
254                 if (p_umv_buf->output_size < sizeof(struct ibv_modify_qp_resp) ||\r
255                         !p_umv_buf->p_inout_buf) {\r
256                         status = IB_INVALID_PARAMETER;\r
257                         goto err_inval_params;\r
258                 }\r
259         }\r
260         \r
261         // fill parameters \r
262         status = to_qp_attr( p_ib_qp, from_qp_type(p_ib_qp->qp_type), \r
263                 p_modify_attr,  &qp_attr, &qp_attr_mask );\r
264         if (status == IB_NOT_DONE)\r
265                 goto query_qp;\r
266         if (status != IB_SUCCESS ) \r
267                 goto err_mode_unsupported;\r
268 \r
269         // modify QP\r
270         err = p_ib_qp->device->modify_qp( p_ib_qp, &qp_attr, qp_attr_mask, NULL);\r
271         if (err) {\r
272                 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_QP,\r
273                         ("ibv_modify_qp failed (%d)\n", err));\r
274                 status = errno_to_iberr(err);\r
275                 goto err_modify_qp;\r
276         }\r
277 \r
278         // Query QP to obtain requested attributes\r
279 query_qp:       \r
280         if (p_qp_attr) {\r
281                 status = mlnx_query_qp ((ib_qp_handle_t)p_ib_qp, p_qp_attr, p_umv_buf);\r
282                 if (status != IB_SUCCESS)\r
283                                 goto err_query_qp;\r
284         }\r
285         \r
286         if( p_umv_buf && p_umv_buf->command ) {\r
287                 struct ibv_modify_qp_resp resp;\r
288                 resp.attr_mask = qp_attr_mask;\r
289                 resp.qp_state = qp_attr.qp_state;\r
290                 err = to_umv_buf(p_umv_buf, &resp, sizeof(struct ibv_modify_qp_resp));\r
291                 if (err) {\r
292                         HCA_PRINT(TRACE_LEVEL_ERROR  , HCA_DBG_SHIM  ,("to_umv_buf failed (%d)\n", err));\r
293                         status = errno_to_iberr(err);\r
294                         goto err_copy;\r
295                 }\r
296         }\r
297 \r
298         status = IB_SUCCESS;\r
299 \r
300 err_copy:       \r
301 err_query_qp:\r
302 err_modify_qp:  \r
303 err_mode_unsupported:\r
304 err_inval_params:\r
305         if (p_umv_buf && p_umv_buf->command) \r
306                 p_umv_buf->status = status;\r
307         if (status != IB_SUCCESS) {\r
308                 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_QP,\r
309                         ("completes with ERROR status %x\n", status));\r
310         }\r
311         HCA_EXIT(HCA_DBG_QP);\r
312         return status;\r
313 }\r
314 \r
315 ib_api_status_t\r
316 mlnx_ndi_modify_qp (\r
317         IN              const   ib_qp_handle_t                          h_qp,\r
318         IN              const   ib_qp_mod_t                                     *p_modify_attr,\r
319                 OUT                     ib_qp_attr_t                            *p_qp_attr OPTIONAL,\r
320         IN              const   uint32_t                                        buf_size,\r
321         IN                              uint8_t* const                          p_outbuf)\r
322 {\r
323         ci_umv_buf_t umv_buf;\r
324         ib_api_status_t status;\r
325         struct ibv_modify_qp_resp resp;\r
326         void *buf = &resp;\r
327 \r
328         HCA_ENTER(HCA_DBG_QP);\r
329 \r
330         /* imitate umv_buf */\r
331         umv_buf.command = TRUE; /* special case for NDI. Usually it's TRUE */\r
332         umv_buf.input_size = 0;\r
333         umv_buf.output_size = sizeof(struct ibv_modify_qp_resp);\r
334         umv_buf.p_inout_buf = (ULONG_PTR)buf;\r
335 \r
336         status = mlnx_modify_qp ( h_qp, p_modify_attr, p_qp_attr, &umv_buf );\r
337 \r
338         if (status == IB_SUCCESS) {\r
339                 cl_memclr( p_outbuf, buf_size );\r
340                 *p_outbuf = resp.qp_state;\r
341         }\r
342 \r
343         HCA_EXIT(HCA_DBG_QP);\r
344         return status;\r
345 }\r
346 \r
347 ib_api_status_t\r
348 mlnx_destroy_qp (\r
349         IN              const   ib_qp_handle_t                          h_qp,\r
350         IN              const   uint64_t                                        timewait )\r
351 {\r
352         ib_api_status_t         status;\r
353         int err;\r
354         struct ib_qp *p_ib_qp = (struct ib_qp *)h_qp;\r
355 \r
356         UNUSED_PARAM( timewait );\r
357 \r
358         HCA_ENTER( HCA_DBG_QP);\r
359 \r
360         HCA_PRINT(TRACE_LEVEL_INFORMATION       ,HCA_DBG_SHIM  ,\r
361                 ("qpnum %#x, pcs %p\n", p_ib_qp->qp_num, PsGetCurrentProcess()) );\r
362 \r
363         err = ib_destroy_qp( p_ib_qp );\r
364         if (err) {\r
365                 HCA_PRINT(TRACE_LEVEL_ERROR ,HCA_DBG_QP,\r
366                         ("ibv_destroy_qp failed (%d)\n", err));\r
367                 status = errno_to_iberr(err);\r
368                 goto err_destroy_qp;\r
369         }\r
370 \r
371         status = IB_SUCCESS;\r
372 \r
373 err_destroy_qp:\r
374         if (status != IB_SUCCESS)\r
375                 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_QP,\r
376                         ("completes with ERROR status %x\n", status));\r
377         HCA_EXIT(HCA_DBG_QP);\r
378         return status;\r
379 }\r
380 \r
381 void\r
382 mlnx_qp_if(\r
383         IN      OUT                     ci_interface_t                          *p_interface )\r
384 {\r
385         p_interface->create_qp = mlnx_create_qp;\r
386         p_interface->create_spl_qp = mlnx_create_spl_qp;\r
387         p_interface->modify_qp = mlnx_modify_qp;\r
388         p_interface->ndi_modify_qp = mlnx_ndi_modify_qp;\r
389         p_interface->query_qp = mlnx_query_qp;\r
390         p_interface->destroy_qp = mlnx_destroy_qp;\r
391 }\r
392 \r