[readline] Extend maximum read line length to 1024 characters
[ipxe.git] / src / net / infiniband / ib_cmrc.c
1 /*
2 * Copyright (C) 2009 Fen Systems Ltd <mbrown@fensystems.co.uk>.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28 * OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 FILE_LICENCE ( BSD2 );
32
33 #include <stdlib.h>
34 #include <string.h>
35 #include <errno.h>
36 #include <ipxe/iobuf.h>
37 #include <ipxe/xfer.h>
38 #include <ipxe/process.h>
39 #include <ipxe/infiniband.h>
40 #include <ipxe/ib_cm.h>
41 #include <ipxe/ib_cmrc.h>
42
43 /**
44 * @file
45 *
46 * Infiniband Communication-managed Reliable Connections
47 *
48 */
49
50 /** CMRC number of send WQEs
51 *
52 * This is a policy decision.
53 */
54 #define IB_CMRC_NUM_SEND_WQES 4
55
56 /** CMRC number of receive WQEs
57 *
58 * This is a policy decision.
59 */
60 #define IB_CMRC_NUM_RECV_WQES 2
61
62 /** CMRC number of completion queue entries
63 *
64 * This is a policy decision
65 */
66 #define IB_CMRC_NUM_CQES 8
67
68 /** An Infiniband Communication-Managed Reliable Connection */
69 struct ib_cmrc_connection {
70 /** Reference count */
71 struct refcnt refcnt;
72 /** Name */
73 const char *name;
74 /** Data transfer interface */
75 struct interface xfer;
76 /** Infiniband device */
77 struct ib_device *ibdev;
78 /** Completion queue */
79 struct ib_completion_queue *cq;
80 /** Queue pair */
81 struct ib_queue_pair *qp;
82 /** Connection */
83 struct ib_connection *conn;
84 /** Destination GID */
85 union ib_gid dgid;
86 /** Service ID */
87 union ib_guid service_id;
88 /** QP is connected */
89 int connected;
90 /** Shutdown process */
91 struct process shutdown;
92 };
93
94 /**
95 * Shut down CMRC connection gracefully
96 *
97 * @v cmrc Communication-Managed Reliable Connection
98 *
99 * The Infiniband data structures are not reference-counted or
100 * guarded. It is therefore unsafe to shut them down while we may be
101 * in the middle of a callback from the Infiniband stack (e.g. in a
102 * receive completion handler).
103 *
104 * This shutdown process will run some time after the call to
105 * ib_cmrc_close(), after control has returned out of the Infiniband
106 * core, and will shut down the Infiniband interfaces cleanly.
107 *
108 * The shutdown process holds an implicit reference on the CMRC
109 * connection, ensuring that the structure is not freed before the
110 * shutdown process has run.
111 */
112 static void ib_cmrc_shutdown ( struct ib_cmrc_connection *cmrc ) {
113 struct ib_device *ibdev = cmrc->ibdev;
114
115 DBGC ( cmrc, "CMRC %s %s shutting down\n",
116 ibdev->name, cmrc->name );
117
118 /* Shut down Infiniband interface */
119 ib_destroy_conn ( ibdev, cmrc->qp, cmrc->conn );
120 ib_destroy_qp ( ibdev, cmrc->qp );
121 ib_destroy_cq ( ibdev, cmrc->cq );
122 ib_close ( ibdev );
123
124 /* Cancel any pending shutdown */
125 process_del ( &cmrc->shutdown );
126
127 /* Drop the remaining reference */
128 ref_put ( &cmrc->refcnt );
129 }
130
131 /**
132 * Close CMRC connection
133 *
134 * @v cmrc Communication-Managed Reliable Connection
135 * @v rc Reason for close
136 */
137 static void ib_cmrc_close ( struct ib_cmrc_connection *cmrc, int rc ) {
138
139 /* Close data transfer interface */
140 intf_shutdown ( &cmrc->xfer, rc );
141
142 /* Schedule shutdown process */
143 process_add ( &cmrc->shutdown );
144 }
145
146 /**
147 * Handle change of CMRC connection status
148 *
149 * @v ibdev Infiniband device
150 * @v qp Queue pair
151 * @v conn Connection
152 * @v rc_cm Connection status code
153 * @v private_data Private data, if available
154 * @v private_data_len Length of private data
155 */
156 static void ib_cmrc_changed ( struct ib_device *ibdev,
157 struct ib_queue_pair *qp,
158 struct ib_connection *conn __unused, int rc_cm,
159 void *private_data, size_t private_data_len ) {
160 struct ib_cmrc_connection *cmrc = ib_qp_get_ownerdata ( qp );
161 int rc_xfer;
162
163 /* Record connection status */
164 if ( rc_cm == 0 ) {
165 DBGC ( cmrc, "CMRC %s %s connected\n",
166 ibdev->name, cmrc->name );
167 cmrc->connected = 1;
168 } else {
169 DBGC ( cmrc, "CMRC %s %s disconnected: %s\n",
170 ibdev->name, cmrc->name, strerror ( rc_cm ) );
171 cmrc->connected = 0;
172 }
173
174 /* Pass up any private data */
175 DBGC2 ( cmrc, "CMRC %s %s received private data:\n",
176 ibdev->name, cmrc->name );
177 DBGC2_HDA ( cmrc, 0, private_data, private_data_len );
178 if ( private_data &&
179 ( rc_xfer = xfer_deliver_raw ( &cmrc->xfer, private_data,
180 private_data_len ) ) != 0 ) {
181 DBGC ( cmrc, "CMRC %s %s could not deliver private data: %s\n",
182 ibdev->name, cmrc->name, strerror ( rc_xfer ) );
183 ib_cmrc_close ( cmrc, rc_xfer );
184 return;
185 }
186
187 /* Notify upper connection of window change */
188 xfer_window_changed ( &cmrc->xfer );
189
190 /* If we are disconnected, close the upper connection */
191 if ( rc_cm != 0 ) {
192 ib_cmrc_close ( cmrc, rc_cm );
193 return;
194 }
195 }
196
197 /** CMRC connection operations */
198 static struct ib_connection_operations ib_cmrc_conn_op = {
199 .changed = ib_cmrc_changed,
200 };
201
202 /**
203 * Handle CMRC send completion
204 *
205 * @v ibdev Infiniband device
206 * @v qp Queue pair
207 * @v iobuf I/O buffer
208 * @v rc Completion status code
209 */
210 static void ib_cmrc_complete_send ( struct ib_device *ibdev,
211 struct ib_queue_pair *qp,
212 struct io_buffer *iobuf, int rc ) {
213 struct ib_cmrc_connection *cmrc = ib_qp_get_ownerdata ( qp );
214
215 /* Free the completed I/O buffer */
216 free_iob ( iobuf );
217
218 /* Close the connection on any send errors */
219 if ( rc != 0 ) {
220 DBGC ( cmrc, "CMRC %s %s send error: %s\n",
221 ibdev->name, cmrc->name, strerror ( rc ) );
222 ib_cmrc_close ( cmrc, rc );
223 return;
224 }
225 }
226
227 /**
228 * Handle CMRC receive completion
229 *
230 * @v ibdev Infiniband device
231 * @v qp Queue pair
232 * @v dest Destination address vector, or NULL
233 * @v source Source address vector, or NULL
234 * @v iobuf I/O buffer
235 * @v rc Completion status code
236 */
237 static void ib_cmrc_complete_recv ( struct ib_device *ibdev,
238 struct ib_queue_pair *qp,
239 struct ib_address_vector *dest __unused,
240 struct ib_address_vector *source __unused,
241 struct io_buffer *iobuf, int rc ) {
242 struct ib_cmrc_connection *cmrc = ib_qp_get_ownerdata ( qp );
243
244 /* Close the connection on any receive errors */
245 if ( rc != 0 ) {
246 DBGC ( cmrc, "CMRC %s %s receive error: %s\n",
247 ibdev->name, cmrc->name, strerror ( rc ) );
248 free_iob ( iobuf );
249 ib_cmrc_close ( cmrc, rc );
250 return;
251 }
252
253 DBGC2 ( cmrc, "CMRC %s %s received:\n", ibdev->name, cmrc->name );
254 DBGC2_HDA ( cmrc, 0, iobuf->data, iob_len ( iobuf ) );
255
256 /* Pass up data */
257 if ( ( rc = xfer_deliver_iob ( &cmrc->xfer, iobuf ) ) != 0 ) {
258 DBGC ( cmrc, "CMRC %s %s could not deliver data: %s\n",
259 ibdev->name, cmrc->name, strerror ( rc ) );
260 ib_cmrc_close ( cmrc, rc );
261 return;
262 }
263 }
264
265 /** Infiniband CMRC completion operations */
266 static struct ib_completion_queue_operations ib_cmrc_completion_ops = {
267 .complete_send = ib_cmrc_complete_send,
268 .complete_recv = ib_cmrc_complete_recv,
269 };
270
271 /** Infiniband CMRC queue pair operations */
272 static struct ib_queue_pair_operations ib_cmrc_queue_pair_ops = {
273 .alloc_iob = alloc_iob,
274 };
275
276 /**
277 * Send data via CMRC
278 *
279 * @v cmrc CMRC connection
280 * @v iobuf Datagram I/O buffer
281 * @v meta Data transfer metadata
282 * @ret rc Return status code
283 */
284 static int ib_cmrc_xfer_deliver ( struct ib_cmrc_connection *cmrc,
285 struct io_buffer *iobuf,
286 struct xfer_metadata *meta __unused ) {
287 struct ib_device *ibdev = cmrc->ibdev;
288 int rc;
289
290 /* If no connection has yet been attempted, send this datagram
291 * as the CM REQ private data. Otherwise, send it via the QP.
292 */
293 if ( ! cmrc->connected ) {
294
295 /* Abort if we have already sent a CM connection request */
296 if ( cmrc->conn ) {
297 DBGC ( cmrc, "CMRC %s %s attempt to send before "
298 "connection is complete\n",
299 ibdev->name, cmrc->name );
300 rc = -EIO;
301 goto out;
302 }
303
304 /* Send via CM connection request */
305 cmrc->conn = ib_create_conn ( cmrc->ibdev, cmrc->qp,
306 &cmrc->dgid, &cmrc->service_id,
307 iobuf->data, iob_len ( iobuf ),
308 &ib_cmrc_conn_op );
309 if ( ! cmrc->conn ) {
310 DBGC ( cmrc, "CMRC %s %s could not connect\n",
311 ibdev->name, cmrc->name );
312 rc = -ENOMEM;
313 goto out;
314 }
315 DBGC ( cmrc, "CMRC %s %s using CM %08x\n",
316 ibdev->name, cmrc->name, cmrc->conn->local_id );
317
318 } else {
319
320 /* Send via QP */
321 if ( ( rc = ib_post_send ( cmrc->ibdev, cmrc->qp, NULL,
322 iob_disown ( iobuf ) ) ) != 0 ) {
323 DBGC ( cmrc, "CMRC %s %s could not send: %s\n",
324 ibdev->name, cmrc->name, strerror ( rc ) );
325 goto out;
326 }
327
328 }
329 return 0;
330
331 out:
332 /* Free the I/O buffer if necessary */
333 free_iob ( iobuf );
334
335 /* Close the connection on any errors */
336 if ( rc != 0 )
337 ib_cmrc_close ( cmrc, rc );
338
339 return rc;
340 }
341
342 /**
343 * Check CMRC flow control window
344 *
345 * @v cmrc CMRC connection
346 * @ret len Length of window
347 */
348 static size_t ib_cmrc_xfer_window ( struct ib_cmrc_connection *cmrc ) {
349
350 /* We indicate a window only when we are successfully
351 * connected.
352 */
353 return ( cmrc->connected ? IB_MAX_PAYLOAD_SIZE : 0 );
354 }
355
356 /**
357 * Identify device underlying CMRC connection
358 *
359 * @v cmrc CMRC connection
360 * @ret device Underlying device
361 */
362 static struct device *
363 ib_cmrc_identify_device ( struct ib_cmrc_connection *cmrc ) {
364 return cmrc->ibdev->dev;
365 }
366
367 /** CMRC data transfer interface operations */
368 static struct interface_operation ib_cmrc_xfer_operations[] = {
369 INTF_OP ( xfer_deliver, struct ib_cmrc_connection *,
370 ib_cmrc_xfer_deliver ),
371 INTF_OP ( xfer_window, struct ib_cmrc_connection *,
372 ib_cmrc_xfer_window ),
373 INTF_OP ( intf_close, struct ib_cmrc_connection *, ib_cmrc_close ),
374 INTF_OP ( identify_device, struct ib_cmrc_connection *,
375 ib_cmrc_identify_device ),
376 };
377
378 /** CMRC data transfer interface descriptor */
379 static struct interface_descriptor ib_cmrc_xfer_desc =
380 INTF_DESC ( struct ib_cmrc_connection, xfer, ib_cmrc_xfer_operations );
381
382 /** CMRC shutdown process descriptor */
383 static struct process_descriptor ib_cmrc_shutdown_desc =
384 PROC_DESC_ONCE ( struct ib_cmrc_connection, shutdown,
385 ib_cmrc_shutdown );
386
387 /**
388 * Open CMRC connection
389 *
390 * @v xfer Data transfer interface
391 * @v ibdev Infiniband device
392 * @v dgid Destination GID
393 * @v service_id Service ID
394 * @v name Connection name
395 * @ret rc Returns status code
396 */
397 int ib_cmrc_open ( struct interface *xfer, struct ib_device *ibdev,
398 union ib_gid *dgid, union ib_guid *service_id,
399 const char *name ) {
400 struct ib_cmrc_connection *cmrc;
401 int rc;
402
403 /* Allocate and initialise structure */
404 cmrc = zalloc ( sizeof ( *cmrc ) );
405 if ( ! cmrc ) {
406 rc = -ENOMEM;
407 goto err_alloc;
408 }
409 ref_init ( &cmrc->refcnt, NULL );
410 cmrc->name = name;
411 intf_init ( &cmrc->xfer, &ib_cmrc_xfer_desc, &cmrc->refcnt );
412 cmrc->ibdev = ibdev;
413 memcpy ( &cmrc->dgid, dgid, sizeof ( cmrc->dgid ) );
414 memcpy ( &cmrc->service_id, service_id, sizeof ( cmrc->service_id ) );
415 process_init_stopped ( &cmrc->shutdown, &ib_cmrc_shutdown_desc,
416 &cmrc->refcnt );
417
418 /* Open Infiniband device */
419 if ( ( rc = ib_open ( ibdev ) ) != 0 ) {
420 DBGC ( cmrc, "CMRC %s %s could not open device: %s\n",
421 ibdev->name, cmrc->name, strerror ( rc ) );
422 goto err_open;
423 }
424
425 /* Create completion queue */
426 if ( ( rc = ib_create_cq ( ibdev, IB_CMRC_NUM_CQES,
427 &ib_cmrc_completion_ops, &cmrc->cq ) ) != 0){
428 DBGC ( cmrc, "CMRC %s %s could not create completion queue: "
429 "%s\n", ibdev->name, cmrc->name, strerror ( rc ) );
430 goto err_create_cq;
431 }
432
433 /* Create queue pair */
434 if ( ( rc = ib_create_qp ( ibdev, IB_QPT_RC, IB_CMRC_NUM_SEND_WQES,
435 cmrc->cq, IB_CMRC_NUM_RECV_WQES, cmrc->cq,
436 &ib_cmrc_queue_pair_ops, name,
437 &cmrc->qp ) ) != 0 ) {
438 DBGC ( cmrc, "CMRC %s %s could not create queue pair: %s\n",
439 ibdev->name, cmrc->name, strerror ( rc ) );
440 goto err_create_qp;
441 }
442 ib_qp_set_ownerdata ( cmrc->qp, cmrc );
443 DBGC ( cmrc, "CMRC %s %s using QPN %#lx\n",
444 ibdev->name, cmrc->name, cmrc->qp->qpn );
445
446 /* Attach to parent interface, transfer reference (implicitly)
447 * to our shutdown process, and return.
448 */
449 intf_plug_plug ( &cmrc->xfer, xfer );
450 return 0;
451
452 ib_destroy_qp ( ibdev, cmrc->qp );
453 err_create_qp:
454 ib_destroy_cq ( ibdev, cmrc->cq );
455 err_create_cq:
456 ib_close ( ibdev );
457 err_open:
458 ref_put ( &cmrc->refcnt );
459 err_alloc:
460 return rc;
461 }