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
6 * This software is available to you under the OpenIB.org BSD license
\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
13 * - Redistributions of source code must retain the above
\r
14 * copyright notice, this list of conditions and the following
\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
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
31 * $Id: al.c 1611 2006-08-20 14:48:55Z sleybo $
\r
34 #include "precomp.h"
\r
36 #if defined(EVENT_TRACING)
\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
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
57 UNREFERENCED_PARAMETER(p_umv_buf);
\r
59 HCA_ENTER( HCA_DBG_QP);
\r
63 status = IB_INVALID_PARAMETER;
\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
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
78 status = from_qp_attr( p_ib_qp, &qp_attr, p_qp_attr );
\r
82 HCA_EXIT(HCA_DBG_QP);
\r
86 static ib_api_status_t
\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 ci_async_event_cb_t event_handler,
\r
92 IN const ib_qp_create_t *p_create_attr,
\r
93 OUT ib_qp_attr_t *p_qp_attr,
\r
94 OUT ib_qp_handle_t *ph_qp,
\r
95 IN OUT ci_umv_buf_t *p_umv_buf )
\r
98 ib_api_status_t status;
\r
99 struct ib_qp * p_ib_qp;
\r
100 struct ib_qp_init_attr qp_init_attr;
\r
101 struct ib_ucontext *p_uctx = NULL;
\r
102 struct ib_pd *p_ib_pd = (struct ib_pd *)h_pd;
\r
103 struct ibv_create_qp *p_req = NULL;
\r
105 HCA_ENTER(HCA_DBG_QP);
\r
107 if( p_umv_buf && p_umv_buf->command ) {
\r
109 if (p_umv_buf->input_size < sizeof(struct ibv_create_qp) ||
\r
110 p_umv_buf->output_size < sizeof(struct ibv_create_qp_resp) ||
\r
111 !p_umv_buf->p_inout_buf) {
\r
112 status = IB_INVALID_PARAMETER;
\r
113 goto err_inval_params;
\r
115 p_req = (struct ibv_create_qp*)(ULONG_PTR)p_umv_buf->p_inout_buf;
\r
116 p_uctx = p_ib_pd->p_uctx;
\r
119 // prepare the parameters
\r
120 RtlZeroMemory(&qp_init_attr, sizeof(qp_init_attr));
\r
121 qp_init_attr.event_handler = event_handler;
\r
122 qp_init_attr.qp_context = (void*)qp_uctx;
\r
123 qp_init_attr.send_cq = (struct ib_cq *)p_create_attr->h_sq_cq;
\r
124 qp_init_attr.recv_cq = (struct ib_cq *)p_create_attr->h_rq_cq;
\r
125 qp_init_attr.srq = (struct ib_srq *)p_create_attr->h_srq;
\r
126 if( p_umv_buf && p_umv_buf->command ) {
\r
127 qp_init_attr.cap.max_recv_sge = p_req->max_recv_sge;
\r
128 qp_init_attr.cap.max_send_sge = p_req->max_send_sge;
\r
129 qp_init_attr.cap.max_recv_wr = p_req->max_recv_wr;
\r
130 qp_init_attr.cap.max_send_wr = p_req->max_send_wr;
\r
131 qp_init_attr.cap.max_inline_data = p_req->max_inline_data;
\r
134 qp_init_attr.cap.max_recv_sge = p_create_attr->rq_sge;
\r
135 qp_init_attr.cap.max_send_sge = p_create_attr->sq_sge;
\r
136 qp_init_attr.cap.max_recv_wr = p_create_attr->rq_depth;
\r
137 qp_init_attr.cap.max_send_wr = p_create_attr->sq_depth;
\r
138 qp_init_attr.cap.max_inline_data = 0; /* absent in IBAL */
\r
140 qp_init_attr.sq_sig_type = (p_create_attr->sq_signaled) ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
\r
141 qp_init_attr.qp_type = to_qp_type(p_create_attr->qp_type);
\r
142 qp_init_attr.port_num = port_num;
\r
143 qp_init_attr.create_flags |= IB_QP_CREATE_IPOIB_UD_LSO;
\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
155 // Query QP to obtain requested attributes
\r
157 status = mlnx_query_qp((ib_qp_handle_t)p_ib_qp, p_qp_attr, p_umv_buf);
\r
158 if (status != IB_SUCCESS)
\r
162 // return the results
\r
163 if (ph_qp) *ph_qp = (ib_qp_handle_t)p_ib_qp;
\r
165 status = IB_SUCCESS;
\r
169 ib_destroy_qp( p_ib_qp );
\r
173 if (p_umv_buf && p_umv_buf->command)
\r
174 p_umv_buf->status = status;
\r
175 if (status != IB_SUCCESS)
\r
176 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_QP,
\r
177 ("completes with ERROR status %x\n", status));
\r
178 HCA_EXIT(HCA_DBG_QP);
\r
183 mlnx_create_spl_qp (
\r
184 IN const ib_pd_handle_t h_pd,
\r
185 IN const uint8_t port_num,
\r
186 IN const void *qp_uctx,
\r
187 IN ci_async_event_cb_t event_handler,
\r
188 IN const ib_qp_create_t *p_create_attr,
\r
189 OUT ib_qp_attr_t *p_qp_attr,
\r
190 OUT ib_qp_handle_t *ph_qp )
\r
192 ib_api_status_t status;
\r
194 HCA_ENTER(HCA_DBG_SHIM);
\r
196 status = __create_qp( h_pd, port_num,
\r
197 qp_uctx, event_handler, p_create_attr, p_qp_attr, ph_qp, NULL );
\r
199 if (status != IB_SUCCESS)
\r
200 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_QP,
\r
201 ("completes with ERROR status %x\n", status));
\r
202 HCA_EXIT(HCA_DBG_QP);
\r
208 IN const ib_pd_handle_t h_pd,
\r
209 IN const void *qp_uctx,
\r
210 IN ci_async_event_cb_t event_handler,
\r
211 IN const ib_qp_create_t *p_create_attr,
\r
212 OUT ib_qp_attr_t *p_qp_attr,
\r
213 OUT ib_qp_handle_t *ph_qp,
\r
214 IN OUT ci_umv_buf_t *p_umv_buf )
\r
216 ib_api_status_t status;
\r
218 //NB: algorithm of mthca_alloc_sqp() requires port_num
\r
219 // PRM states, that special pares are created in couples, so
\r
220 // looks like we can put here port_num = 1 always
\r
221 uint8_t port_num = 1;
\r
223 HCA_ENTER(HCA_DBG_QP);
\r
225 status = __create_qp( h_pd, port_num,
\r
226 qp_uctx, event_handler, p_create_attr, p_qp_attr, ph_qp, p_umv_buf );
\r
228 if (status != IB_SUCCESS)
\r
229 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_QP,
\r
230 ("completes with ERROR status %x\n", status));
\r
231 HCA_EXIT(HCA_DBG_QP);
\r
237 IN const ib_qp_handle_t h_qp,
\r
238 IN const ib_qp_mod_t *p_modify_attr,
\r
239 OUT ib_qp_attr_t *p_qp_attr OPTIONAL,
\r
240 IN OUT ci_umv_buf_t *p_umv_buf OPTIONAL )
\r
243 ib_api_status_t status;
\r
244 struct ib_qp_attr qp_attr;
\r
246 struct ib_qp *p_ib_qp = (struct ib_qp *)h_qp;
\r
248 HCA_ENTER(HCA_DBG_QP);
\r
251 if( p_umv_buf && p_umv_buf->command ) {
\r
253 if (p_umv_buf->output_size < sizeof(struct ibv_modify_qp_resp) ||
\r
254 !p_umv_buf->p_inout_buf) {
\r
255 status = IB_INVALID_PARAMETER;
\r
256 goto err_inval_params;
\r
260 // fill parameters
\r
261 status = to_qp_attr( p_ib_qp, from_qp_type(p_ib_qp->qp_type),
\r
262 p_modify_attr, &qp_attr, &qp_attr_mask );
\r
263 if (status == IB_NOT_DONE)
\r
265 if (status != IB_SUCCESS )
\r
266 goto err_mode_unsupported;
\r
269 err = p_ib_qp->device->modify_qp( p_ib_qp, &qp_attr, qp_attr_mask, NULL);
\r
271 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_QP,
\r
272 ("ibv_modify_qp failed (%d)\n", err));
\r
273 status = errno_to_iberr(err);
\r
274 goto err_modify_qp;
\r
277 // Query QP to obtain requested attributes
\r
280 status = mlnx_query_qp ((ib_qp_handle_t)p_ib_qp, p_qp_attr, p_umv_buf);
\r
281 if (status != IB_SUCCESS)
\r
285 if( p_umv_buf && p_umv_buf->command ) {
\r
286 struct ibv_modify_qp_resp resp;
\r
287 resp.attr_mask = qp_attr_mask;
\r
288 resp.qp_state = qp_attr.qp_state;
\r
289 err = to_umv_buf(p_umv_buf, &resp, sizeof(struct ibv_modify_qp_resp));
\r
291 HCA_PRINT(TRACE_LEVEL_ERROR , HCA_DBG_SHIM ,("to_umv_buf failed (%d)\n", err));
\r
292 status = errno_to_iberr(err);
\r
297 status = IB_SUCCESS;
\r
302 err_mode_unsupported:
\r
304 if (p_umv_buf && p_umv_buf->command)
\r
305 p_umv_buf->status = status;
\r
306 if (status != IB_SUCCESS) {
\r
307 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_QP,
\r
308 ("completes with ERROR status %x\n", status));
\r
310 HCA_EXIT(HCA_DBG_QP);
\r
315 mlnx_ndi_modify_qp (
\r
316 IN const ib_qp_handle_t h_qp,
\r
317 IN const ib_qp_mod_t *p_modify_attr,
\r
318 OUT ib_qp_attr_t *p_qp_attr OPTIONAL,
\r
319 IN const uint32_t buf_size,
\r
320 IN uint8_t* const p_outbuf)
\r
322 ci_umv_buf_t umv_buf;
\r
323 ib_api_status_t status;
\r
324 struct ibv_modify_qp_resp resp;
\r
327 HCA_ENTER(HCA_DBG_QP);
\r
329 /* imitate umv_buf */
\r
330 umv_buf.command = TRUE; /* special case for NDI. Usually it's TRUE */
\r
331 umv_buf.input_size = 0;
\r
332 umv_buf.output_size = sizeof(struct ibv_modify_qp_resp);
\r
333 umv_buf.p_inout_buf = (ULONG_PTR)buf;
\r
335 status = mlnx_modify_qp ( h_qp, p_modify_attr, p_qp_attr, &umv_buf );
\r
337 if (status == IB_SUCCESS) {
\r
338 cl_memclr( p_outbuf, buf_size );
\r
339 *p_outbuf = resp.qp_state;
\r
342 HCA_EXIT(HCA_DBG_QP);
\r
348 IN const ib_qp_handle_t h_qp,
\r
349 IN const uint64_t timewait )
\r
351 ib_api_status_t status;
\r
353 struct ib_qp *p_ib_qp = (struct ib_qp *)h_qp;
\r
355 UNUSED_PARAM( timewait );
\r
357 HCA_ENTER( HCA_DBG_QP);
\r
359 HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_SHIM ,
\r
360 ("qpnum %#x, pcs %p\n", p_ib_qp->qp_num, PsGetCurrentProcess()) );
\r
362 err = ib_destroy_qp( p_ib_qp );
\r
364 HCA_PRINT(TRACE_LEVEL_ERROR ,HCA_DBG_QP,
\r
365 ("ibv_destroy_qp failed (%d)\n", err));
\r
366 status = errno_to_iberr(err);
\r
367 goto err_destroy_qp;
\r
370 status = IB_SUCCESS;
\r
373 if (status != IB_SUCCESS)
\r
374 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_QP,
\r
375 ("completes with ERROR status %x\n", status));
\r
376 HCA_EXIT(HCA_DBG_QP);
\r
382 IN OUT ci_interface_t *p_interface )
\r
384 p_interface->create_qp = mlnx_create_qp;
\r
385 p_interface->create_spl_qp = mlnx_create_spl_qp;
\r
386 p_interface->modify_qp = mlnx_modify_qp;
\r
387 p_interface->ndi_modify_qp = mlnx_ndi_modify_qp;
\r
388 p_interface->query_qp = mlnx_query_qp;
\r
389 p_interface->destroy_qp = mlnx_destroy_qp;
\r