00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 FILE_LICENCE ( BSD2 );
00032
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <errno.h>
00036 #include <gpxe/iobuf.h>
00037 #include <gpxe/xfer.h>
00038 #include <gpxe/process.h>
00039 #include <gpxe/infiniband.h>
00040 #include <gpxe/ib_cm.h>
00041 #include <gpxe/ib_cmrc.h>
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 #define IB_CMRC_NUM_SEND_WQES 4
00055
00056
00057
00058
00059
00060 #define IB_CMRC_NUM_RECV_WQES 2
00061
00062
00063
00064
00065
00066 #define IB_CMRC_NUM_CQES 8
00067
00068
00069 struct ib_cmrc_connection {
00070
00071 struct refcnt refcnt;
00072
00073 struct xfer_interface xfer;
00074
00075 struct ib_device *ibdev;
00076
00077 struct ib_completion_queue *cq;
00078
00079 struct ib_queue_pair *qp;
00080
00081 struct ib_connection *conn;
00082
00083 struct ib_gid dgid;
00084
00085 struct ib_gid_half service_id;
00086
00087 int connected;
00088
00089 struct process shutdown;
00090 };
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 static void ib_cmrc_shutdown ( struct process *process ) {
00111 struct ib_cmrc_connection *cmrc =
00112 container_of ( process, struct ib_cmrc_connection, shutdown );
00113
00114 DBGC ( cmrc, "CMRC %p shutting down\n", cmrc );
00115
00116
00117 ib_destroy_conn ( cmrc->ibdev, cmrc->qp, cmrc->conn );
00118 ib_destroy_qp ( cmrc->ibdev, cmrc->qp );
00119 ib_destroy_cq ( cmrc->ibdev, cmrc->cq );
00120 ib_close ( cmrc->ibdev );
00121
00122
00123 process_del ( &cmrc->shutdown );
00124
00125
00126 ref_put ( &cmrc->refcnt );
00127 }
00128
00129
00130
00131
00132
00133
00134
00135 static void ib_cmrc_close ( struct ib_cmrc_connection *cmrc, int rc ) {
00136
00137
00138 xfer_nullify ( &cmrc->xfer );
00139 xfer_close ( &cmrc->xfer, rc );
00140
00141
00142 process_add ( &cmrc->shutdown );
00143 }
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 static void ib_cmrc_changed ( struct ib_device *ibdev __unused,
00156 struct ib_queue_pair *qp,
00157 struct ib_connection *conn __unused, int rc_cm,
00158 void *private_data, size_t private_data_len ) {
00159 struct ib_cmrc_connection *cmrc = ib_qp_get_ownerdata ( qp );
00160 int rc_xfer;
00161
00162
00163 if ( rc_cm == 0 ) {
00164 DBGC ( cmrc, "CMRC %p connected\n", cmrc );
00165 cmrc->connected = 1;
00166 } else {
00167 DBGC ( cmrc, "CMRC %p disconnected: %s\n",
00168 cmrc, strerror ( rc_cm ) );
00169 cmrc->connected = 0;
00170 }
00171
00172
00173 DBGC2 ( cmrc, "CMRC %p received private data:\n", cmrc );
00174 DBGC2_HDA ( cmrc, 0, private_data, private_data_len );
00175 if ( private_data &&
00176 ( rc_xfer = xfer_deliver_raw ( &cmrc->xfer, private_data,
00177 private_data_len ) ) != 0 ) {
00178 DBGC ( cmrc, "CMRC %p could not deliver private data: %s\n",
00179 cmrc, strerror ( rc_xfer ) );
00180 ib_cmrc_close ( cmrc, rc_xfer );
00181 return;
00182 }
00183
00184
00185 if ( rc_cm != 0 ) {
00186 ib_cmrc_close ( cmrc, rc_cm );
00187 return;
00188 }
00189 }
00190
00191
00192 static struct ib_connection_operations ib_cmrc_conn_op = {
00193 .changed = ib_cmrc_changed,
00194 };
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 static void ib_cmrc_complete_send ( struct ib_device *ibdev __unused,
00205 struct ib_queue_pair *qp,
00206 struct io_buffer *iobuf, int rc ) {
00207 struct ib_cmrc_connection *cmrc = ib_qp_get_ownerdata ( qp );
00208
00209
00210 free_iob ( iobuf );
00211
00212
00213 if ( rc != 0 ) {
00214 DBGC ( cmrc, "CMRC %p send error: %s\n",
00215 cmrc, strerror ( rc ) );
00216 ib_cmrc_close ( cmrc, rc );
00217 return;
00218 }
00219 }
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 static void ib_cmrc_complete_recv ( struct ib_device *ibdev __unused,
00231 struct ib_queue_pair *qp,
00232 struct ib_address_vector *av __unused,
00233 struct io_buffer *iobuf, int rc ) {
00234 struct ib_cmrc_connection *cmrc = ib_qp_get_ownerdata ( qp );
00235
00236
00237 if ( rc != 0 ) {
00238 DBGC ( cmrc, "CMRC %p receive error: %s\n",
00239 cmrc, strerror ( rc ) );
00240 free_iob ( iobuf );
00241 ib_cmrc_close ( cmrc, rc );
00242 return;
00243 }
00244
00245 DBGC2 ( cmrc, "CMRC %p received:\n", cmrc );
00246 DBGC2_HDA ( cmrc, 0, iobuf->data, iob_len ( iobuf ) );
00247
00248
00249 if ( ( rc = xfer_deliver_iob ( &cmrc->xfer, iobuf ) ) != 0 ) {
00250 DBGC ( cmrc, "CMRC %p could not deliver data: %s\n",
00251 cmrc, strerror ( rc ) );
00252 ib_cmrc_close ( cmrc, rc );
00253 return;
00254 }
00255 }
00256
00257
00258 static struct ib_completion_queue_operations ib_cmrc_completion_ops = {
00259 .complete_send = ib_cmrc_complete_send,
00260 .complete_recv = ib_cmrc_complete_recv,
00261 };
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 static int ib_cmrc_xfer_deliver_iob ( struct xfer_interface *xfer,
00272 struct io_buffer *iobuf,
00273 struct xfer_metadata *meta __unused ) {
00274 struct ib_cmrc_connection *cmrc =
00275 container_of ( xfer, struct ib_cmrc_connection, xfer );
00276 int rc;
00277
00278
00279
00280
00281 if ( ! cmrc->connected ) {
00282
00283
00284 if ( cmrc->conn ) {
00285 DBGC ( cmrc, "CMRC %p attempt to send before "
00286 "connection is complete\n", cmrc );
00287 rc = -EIO;
00288 goto out;
00289 }
00290
00291
00292 cmrc->conn = ib_create_conn ( cmrc->ibdev, cmrc->qp,
00293 &cmrc->dgid, &cmrc->service_id,
00294 iobuf->data, iob_len ( iobuf ),
00295 &ib_cmrc_conn_op );
00296 if ( ! cmrc->conn ) {
00297 DBGC ( cmrc, "CMRC %p could not connect\n", cmrc );
00298 rc = -ENOMEM;
00299 goto out;
00300 }
00301
00302 } else {
00303
00304
00305 if ( ( rc = ib_post_send ( cmrc->ibdev, cmrc->qp, NULL,
00306 iob_disown ( iobuf ) ) ) != 0 ) {
00307 DBGC ( cmrc, "CMRC %p could not send: %s\n",
00308 cmrc, strerror ( rc ) );
00309 goto out;
00310 }
00311
00312 }
00313 return 0;
00314
00315 out:
00316
00317 free_iob ( iobuf );
00318
00319
00320 if ( rc != 0 )
00321 ib_cmrc_close ( cmrc, rc );
00322
00323 return rc;
00324 }
00325
00326
00327
00328
00329
00330
00331
00332 static size_t ib_cmrc_xfer_window ( struct xfer_interface *xfer ) {
00333 struct ib_cmrc_connection *cmrc =
00334 container_of ( xfer, struct ib_cmrc_connection, xfer );
00335
00336
00337
00338
00339 return ( cmrc->connected ? IB_MAX_PAYLOAD_SIZE : 0 );
00340 }
00341
00342
00343
00344
00345
00346
00347
00348 static void ib_cmrc_xfer_close ( struct xfer_interface *xfer, int rc ) {
00349 struct ib_cmrc_connection *cmrc =
00350 container_of ( xfer, struct ib_cmrc_connection, xfer );
00351
00352 DBGC ( cmrc, "CMRC %p closed: %s\n", cmrc, strerror ( rc ) );
00353 ib_cmrc_close ( cmrc, rc );
00354 }
00355
00356
00357 static struct xfer_interface_operations ib_cmrc_xfer_operations = {
00358 .close = ib_cmrc_xfer_close,
00359 .vredirect = ignore_xfer_vredirect,
00360 .window = ib_cmrc_xfer_window,
00361 .alloc_iob = default_xfer_alloc_iob,
00362 .deliver_iob = ib_cmrc_xfer_deliver_iob,
00363 .deliver_raw = xfer_deliver_as_iob,
00364 };
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 int ib_cmrc_open ( struct xfer_interface *xfer, struct ib_device *ibdev,
00376 struct ib_gid *dgid, struct ib_gid_half *service_id ) {
00377 struct ib_cmrc_connection *cmrc;
00378 int rc;
00379
00380
00381 cmrc = zalloc ( sizeof ( *cmrc ) );
00382 if ( ! cmrc ) {
00383 rc = -ENOMEM;
00384 goto err_alloc;
00385 }
00386 xfer_init ( &cmrc->xfer, &ib_cmrc_xfer_operations, &cmrc->refcnt );
00387 cmrc->ibdev = ibdev;
00388 memcpy ( &cmrc->dgid, dgid, sizeof ( cmrc->dgid ) );
00389 memcpy ( &cmrc->service_id, service_id, sizeof ( cmrc->service_id ) );
00390 process_init_stopped ( &cmrc->shutdown, ib_cmrc_shutdown,
00391 &cmrc->refcnt );
00392
00393
00394 if ( ( rc = ib_open ( ibdev ) ) != 0 ) {
00395 DBGC ( cmrc, "CMRC %p could not open device: %s\n",
00396 cmrc, strerror ( rc ) );
00397 goto err_open;
00398 }
00399
00400
00401 cmrc->cq = ib_create_cq ( ibdev, IB_CMRC_NUM_CQES,
00402 &ib_cmrc_completion_ops );
00403 if ( ! cmrc->cq ) {
00404 DBGC ( cmrc, "CMRC %p could not create completion queue\n",
00405 cmrc );
00406 rc = -ENOMEM;
00407 goto err_create_cq;
00408 }
00409
00410
00411 cmrc->qp = ib_create_qp ( ibdev, IB_QPT_RC, IB_CMRC_NUM_SEND_WQES,
00412 cmrc->cq, IB_CMRC_NUM_RECV_WQES, cmrc->cq );
00413 if ( ! cmrc->qp ) {
00414 DBGC ( cmrc, "CMRC %p could not create queue pair\n", cmrc );
00415 rc = -ENOMEM;
00416 goto err_create_qp;
00417 }
00418 ib_qp_set_ownerdata ( cmrc->qp, cmrc );
00419 DBGC ( cmrc, "CMRC %p using QPN %lx\n", cmrc, cmrc->qp->qpn );
00420
00421
00422
00423
00424 xfer_plug_plug ( &cmrc->xfer, xfer );
00425 return 0;
00426
00427 ib_destroy_qp ( ibdev, cmrc->qp );
00428 err_create_qp:
00429 ib_destroy_cq ( ibdev, cmrc->cq );
00430 err_create_cq:
00431 ib_close ( ibdev );
00432 err_open:
00433 ref_put ( &cmrc->refcnt );
00434 err_alloc:
00435 return rc;
00436 }